fake.txt 7.54 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
The `fake` plugin
=================

The plugin pretends to be bunch of services listening for users to
authenticate. All it does is logging the attempts (and, if configured,
the passwords) and tells the „users“ the password is wrong.

This is a trap for all the password-guessing bots, so we get to know
their IP addresses and block them.

Internal architecture
---------------------

There's a generic central part of the plugin. It manages sockets of
the connections and timeouts on them. It also contains the log cache
and sends the logs to the server whenever necessary. The generic part
reads configuration and modifies the services accordingly.

Implementation of a service provides some descriptions (eg. if the
socket is UDP or TCP and on which port it usually runs) and set of
callbacks. The callbacks are called whenever there's data from a
connected client, a connection is made, etc. It is up to the service
callbacks to log events.

Communication protocol
----------------------

There are just two tasks that are done over the wire. It's configuring
the client and reporting events.

Configuration
~~~~~~~~~~~~~

After connecting, the client sends a message containing just the
opcode `C`. This is request for configuration.

The server responds with a message with opcode `C` and the
configuration. The configuration consists of these items, all are
`uint32_t` in network byte order:

  `version`:: Opaque version number of the config. The
    server guarantees that configuration with the same number is the
    same.
  `max_age`:: Maximum number of milliseconds an event can
    have and still not be sent for storage on the server. It doesn't
    mandate that the server shall be contacted at least that often ‒
    there may be no events, therefore nothing would be too old.
  `max_size`:: The number of bytes the message with log events which
    prompts the client to submit them. This is not strict limit on the
    size ‒ the message may be actually larger, usually by the last
    event.
  `max_attempts`:: How many attempts from a single attacker are enough
    to trigger sending of the log events. If someone is attacking, it
    is important for the server to know about it soon.
  `throttle_holdback`:: When the `max_attempts` is reached, the same
    attacker doesn't provoke sending of the logs again for this many
    milliseconds. The events are still logged, only the server is
    already informed about that one and it doesn't need to hear it so
    often.

The server may send the configuration at any time, it doesn't need to
be prompted to do so (though it currently sends it only when asked).

Submission of logs
~~~~~~~~~~~~~~~~~~

Whenever the client thinks it is a good time, it submits the logs to
the server. They are all sent inside a single message, prefixed by the
`L` opcode. The events are simply put together linearly.

Each event starts with a header:

  `timestamp`:: `uint32_t`, number of milliseconds specifying the age
    of the event.
  `event_type`:: `uint8_t` which says what kind of event happened:
    connect (0);; The specified client connected.
    disconnect (1);; The connection was terminated gracefully (whatever it
      means for the given protocol).
    lost (2);; The connection was terminated in some erroneous way.
    connect extra (3);; Another attempt to connect happened while the
      limit of connections for given protocol was already reached.
      Such connection was refused.
    timeout (4);; The client was silent for too long. This implies
      termination of the connection.
    login (5);; The client tried to log in.
  `addr_type`:: `uint8_t`, the type of address. Currently, IPv4 (0)
    and IPv6 (1) addresses are known.
  `info_count`:: `uint8_t`, number of additional records accompanying
    this log event.
  `code`:: `char`, representing which service generated the event.
    Currently known ones are:
    `T`;; Telnet service.
93
  `rem_port`:: `uint16_t`, the port of attacker.
94

95
96
97
The header is followed by addresses (the length depends on the address
type, which is specified in the header). The remote one is first, the
local one second.
98
99
100
101
102
103
104
105

The address is followed by corresponding number of additional records.
Each record is prefixed by single `uint8_t` type. Current types are:

  name (0):: The login name tried by the attacker.
  password (1):: The password tried by the attacker.
  reason (2):: The reason for the event. Not all events have reasons,
    this is usually with some kind of connection termination.
106
107
108
  method (3):: Request method (GET/PUT…)
  uri (4):: Uri (or part of thereof)
  host (5):: Hostname
109
110
111
112

The type of the record is followed by a single string, encoded in the
usual uplink format (`uint32_t` length, followed by so many
characters).
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

Uci configuration
-----------------

There are two levels of configuration. One is read directly by the
plugin and it is part of the `plugin` section. This one is generated
by the init script and isn't expected to be edited by user.

The other is in a separate section of type `fakes` and it is expected
to be edited by user. This provides information to the init script.

The `plugin` section
~~~~~~~~~~~~~~~~~~~~

This is the same `plugin` section that tells ucollect to load this
plugin. There are, however, additional options:

130
131
132
133
134
135
136
137
 `log_credentials`::
   If this is set to 1, the login names and passwords the attackers
   try are sent together with the events. If it is set to 0, only the
   events are logged, but without this additional info. If the option
   is not present, it defaults to 0.
 `telnet_port`::
   The port on which the plugin listens on the telnet protocol. If it
   is set to 0, listening to telnet protocol is disabled.
138
139
140
 `telnet_alt_port`::
   Another port on which the plugin listens on the telnet protocol. If it
   is set to 0, listening to telnet protocol is disabled.
141
142
143
 `http_port`::
   The port on which the plugin listens on the http protocol. If it is
   set to 0, it gets disabled.
144
145

Further service-specific port options are to come with the services.
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

The `fakes` section
~~~~~~~~~~~~~~~~~~~

This section is not directly processed by the plugin code. It is used
to feed the firewall and to create the above configuration.

The section is of type `fakes` and its name is also `fakes`.

The options are:

  `disable`:: This is actually a list. Each item marks one port and
    protocol which should be left alone. All items are in the form of
    port number directly followed by `tcp` or `udp` (without any
    separator). So, to disable telnet, you'd put `23tcp` into the list.
  `redir_offset`::
    The real port, where ucollect listens, is different than the one
    the attacker connects to. It is then redirected by the firewall.
    The `redir_offset` specifies the distance of the ports (the real
    one is by this amount higher). You may want to change it if the
    real port collides with a service on the router.
  `mark_mask`::
    The firewall uses the mark mechanism of iptables. It needs two
    bits of information and it uses the bits specified by mask
    `0xC0000` by default. If this collides with some other system
    using the marks, you can change the mask and the values in the
    following options.
  `mark_port_ok`::
    A value marking packets with a port to one of the interesting
    services. It must be non-zero value composed from the bits of
    `mark_mask` and distinct from the others.
  `mark_addr_ok`::
    A value marking packets with matching port and address. It is
    similar to the `mark_port_ok` value, but it needs a distinct
    value.
  `mark_redir`::
    A value marking packets selected for redirection. Again, similar
    to the above two and needs a distinct value.