mirror of
https://github.com/zeek/zeek.git
synced 2025-10-03 07:08:19 +00:00
Merge remote-tracking branch 'origin/topic/seth/tunnels-merge'
* origin/topic/seth/tunnels-merge: SOCKS DPD fixes. Fix a bug in the SOCKS analyzer. SOCKS and tunnel test updates. Updates for the SOCKS analyzer. Very small updates to the tunnels framework.
This commit is contained in:
commit
6cda00c75e
30 changed files with 524 additions and 127 deletions
|
@ -162,33 +162,50 @@ signature dpd_teredo {
|
|||
enable "teredo"
|
||||
}
|
||||
|
||||
signature dpd_socks_client {
|
||||
signature dpd_socks4_client {
|
||||
ip-proto == tcp
|
||||
# '32' is a rather arbitrary max length for the user name.
|
||||
payload /^\x04[\x01\x02].{0,32}\x00/
|
||||
tcp-state originator
|
||||
}
|
||||
|
||||
signature dpd_socks_server {
|
||||
signature dpd_socks4_server {
|
||||
ip-proto == tcp
|
||||
requires-reverse-signature dpd_socks_client
|
||||
requires-reverse-signature dpd_socks4_client
|
||||
payload /^\x00[\x5a\x5b\x5c\x5d]/
|
||||
tcp-state responder
|
||||
enable "socks"
|
||||
}
|
||||
|
||||
signature dpd_socks_reverse_client {
|
||||
signature dpd_socks4_reverse_client {
|
||||
ip-proto == tcp
|
||||
# '32' is a rather arbitrary max length for the user name.
|
||||
payload /^\x04[\x01\x02].{0,32}\x00/
|
||||
tcp-state responder
|
||||
}
|
||||
|
||||
signature dpd_socks_reverse_server {
|
||||
signature dpd_socks4_reverse_server {
|
||||
ip-proto == tcp
|
||||
requires-reverse-signature dpd_socks_client
|
||||
requires-reverse-signature dpd_socks4_reverse_client
|
||||
payload /^\x00[\x5a\x5b\x5c\x5d]/
|
||||
tcp-state originator
|
||||
enable "socks"
|
||||
}
|
||||
|
||||
signature dpd_socks5_client {
|
||||
ip-proto == tcp
|
||||
# Watch for a few authentication methods to reduce false positives.
|
||||
payload /^\x05.[\x00\x01\x02]/
|
||||
tcp-state originator
|
||||
}
|
||||
|
||||
signature dpd_socks5_server {
|
||||
ip-proto == tcp
|
||||
requires-reverse-signature dpd_socks5_client
|
||||
# Watch for a single authentication method to be chosen by the server.
|
||||
payload /^\x05\x01[\x00\x01\x02]/
|
||||
tcp-state responder
|
||||
enable "socks"
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -28,17 +28,20 @@ export {
|
|||
ts: time &log;
|
||||
## The unique identifier for the tunnel, which may correspond
|
||||
## to a :bro:type:`connection`'s *uid* field for non-IP-in-IP tunnels.
|
||||
uid: string &log;
|
||||
## This is optional because there could be numerous connections
|
||||
## for payload proxies like SOCKS but we should treat it as a single
|
||||
## tunnel.
|
||||
uid: string &log &optional;
|
||||
## The tunnel "connection" 4-tuple of endpoint addresses/ports.
|
||||
## For an IP tunnel, the ports will be 0.
|
||||
id: conn_id &log;
|
||||
## The type of activity that occurred.
|
||||
action: Action &log;
|
||||
## The type of tunnel.
|
||||
tunnel_type: Tunnel::Type &log;
|
||||
## The type of activity that occurred.
|
||||
action: Action &log;
|
||||
};
|
||||
|
||||
## Logs all tunnels in an ecapsulation chain with action
|
||||
## Logs all tunnels in an encapsulation chain with action
|
||||
## :bro:see:`Tunnel::DISCOVER` that aren't already in the
|
||||
## :bro:id:`Tunnel::active` table and adds them if not.
|
||||
global register_all: function(ecv: EncapsulatingConnVector);
|
||||
|
@ -71,7 +74,7 @@ export {
|
|||
|
||||
## The amount of time a tunnel is not used in establishment of new
|
||||
## connections before it is considered inactive/expired.
|
||||
const expiration_interval = 24hrs &redef;
|
||||
const expiration_interval = 1hrs &redef;
|
||||
|
||||
## Currently active tunnels. That is, tunnels for which new, encapsulated
|
||||
## connections have been seen in the interval indicated by
|
||||
|
@ -104,7 +107,8 @@ function register(ec: EncapsulatingConn)
|
|||
{
|
||||
local tunnel: Info;
|
||||
tunnel$ts = network_time();
|
||||
tunnel$uid = ec$uid;
|
||||
if ( ec?$uid )
|
||||
tunnel$uid = ec$uid;
|
||||
tunnel$id = ec$cid;
|
||||
tunnel$action = DISCOVER;
|
||||
tunnel$tunnel_type = ec$tunnel_type;
|
||||
|
|
|
@ -191,7 +191,7 @@ export {
|
|||
tunnel_type: Tunnel::Type;
|
||||
## A globally unique identifier that, for non-IP-in-IP tunnels,
|
||||
## cross-references the *uid* field of :bro:type:`connection`.
|
||||
uid: string;
|
||||
uid: string &optional;
|
||||
} &log;
|
||||
} # end export
|
||||
module GLOBAL;
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
@load ./consts
|
||||
@load ./main
|
40
scripts/base/protocols/socks/consts.bro
Normal file
40
scripts/base/protocols/socks/consts.bro
Normal file
|
@ -0,0 +1,40 @@
|
|||
module SOCKS;
|
||||
|
||||
export {
|
||||
type RequestType: enum {
|
||||
CONNECTION = 1,
|
||||
PORT = 2,
|
||||
};
|
||||
|
||||
const v5_authentication_methods: table[count] of string = {
|
||||
[0] = "No Authentication Required",
|
||||
[1] = "GSSAPI",
|
||||
[2] = "Username/Password",
|
||||
[3] = "Challenge-Handshake Authentication Protocol",
|
||||
[5] = "Challenge-Response Authentication Method",
|
||||
[6] = "Secure Sockets Layer",
|
||||
[7] = "NDS Authentication",
|
||||
[8] = "Multi-Authentication Framework",
|
||||
[255] = "No Acceptable Methods",
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
const v4_status: table[count] of string = {
|
||||
[0x5a] = "succeeded",
|
||||
[0x5b] = "general SOCKS server failure",
|
||||
[0x5c] = "request failed because client is not running identd",
|
||||
[0x5d] = "request failed because client's identd could not confirm the user ID string in the request",
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
const v5_status: table[count] of string = {
|
||||
[0] = "succeeded",
|
||||
[1] = "general SOCKS server failure",
|
||||
[2] = "connection not allowed by ruleset",
|
||||
[3] = "Network unreachable",
|
||||
[4] = "Host unreachable",
|
||||
[5] = "Connection refused",
|
||||
[6] = "TTL expired",
|
||||
[7] = "Command not supported",
|
||||
[8] = "Address type not supported",
|
||||
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||
|
||||
}
|
|
@ -1,15 +1,98 @@
|
|||
@load base/frameworks/tunnels
|
||||
@load ./consts
|
||||
|
||||
module SOCKS;
|
||||
|
||||
export {
|
||||
type RequestType: enum {
|
||||
CONNECTION = 1,
|
||||
PORT = 2,
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
type Info: record {
|
||||
## Time when the proxy connection was first detected.
|
||||
ts: time &log;
|
||||
uid: string &log;
|
||||
id: conn_id &log;
|
||||
## Protocol version of SOCKS.
|
||||
version: count &log;
|
||||
## Username for the proxy if extracted from the network.
|
||||
user: string &log &optional;
|
||||
## Server status for the attempt at using the proxy.
|
||||
status: string &log &optional;
|
||||
## Client requested address. Mutually exclusive with req_name.
|
||||
req_h: addr &log &optional;
|
||||
## Client requested domain name. Mutually exclusive with req_h.
|
||||
req_name: string &log &optional;
|
||||
## Client requested port.
|
||||
req_p: port &log &optional;
|
||||
## Server bound address. Mutually exclusive with bound_name.
|
||||
bound_h: addr &log &optional;
|
||||
## Server bound domain name. Mutually exclusive with bound_h.
|
||||
bound_name: string &log &optional;
|
||||
## Server bound port.
|
||||
bound_p: port &log &optional;
|
||||
};
|
||||
|
||||
## Event that can be handled to access the SOCKS
|
||||
## record as it is sent on to the logging framework.
|
||||
global log_socks: event(rec: Info);
|
||||
}
|
||||
|
||||
event socks_request(c: connection, request_type: count, dstaddr: addr, dstname: string, p: port, user: string)
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Tunnel::register([$cid=c$id, $tunnel_type=Tunnel::SOCKS, $uid=c$uid]);
|
||||
Log::create_stream(SOCKS::LOG, [$columns=Info, $ev=log_socks]);
|
||||
}
|
||||
|
||||
redef record connection += {
|
||||
socks: SOCKS::Info &optional;
|
||||
};
|
||||
|
||||
# Configure DPD
|
||||
redef capture_filters += { ["socks"] = "tcp port 1080" };
|
||||
redef dpd_config += { [ANALYZER_SOCKS] = [$ports = set(1080/tcp)] };
|
||||
redef likely_server_ports += { 1080/tcp };
|
||||
|
||||
function set_session(c: connection, version: count)
|
||||
{
|
||||
if ( ! c?$socks )
|
||||
c$socks = [$ts=network_time(), $id=c$id, $uid=c$uid, $version=version];
|
||||
}
|
||||
|
||||
event socks_request(c: connection, version: count, request_type: count,
|
||||
dstaddr: addr, dstname: string, p: port, user: string) &priority=5
|
||||
{
|
||||
set_session(c, version);
|
||||
|
||||
if ( dstaddr != [::] )
|
||||
c$socks$req_h = dstaddr;
|
||||
if ( dstname != "" )
|
||||
c$socks$req_name = dstname;
|
||||
c$socks$req_p = p;
|
||||
|
||||
# Copy this conn_id and set the orig_p to zero because in the case of SOCKS proxies there will
|
||||
# be potentially many source ports since a new proxy connection is established for each
|
||||
# proxied connection. We treat this as a singular "tunnel".
|
||||
local cid = copy(c$id);
|
||||
cid$orig_p = 0/tcp;
|
||||
Tunnel::register([$cid=cid, $tunnel_type=Tunnel::SOCKS, $payload_proxy=T]);
|
||||
}
|
||||
|
||||
event socks_reply(c: connection, version: count, reply: count, dstaddr: addr, dstname: string, p: port) &priority=5
|
||||
{
|
||||
set_session(c, version);
|
||||
|
||||
if ( version == 5 )
|
||||
c$socks$status = v5_status[reply];
|
||||
else if ( version == 4 )
|
||||
c$socks$status = v4_status[reply];
|
||||
|
||||
if ( dstaddr != [::] )
|
||||
c$socks$bound_h = dstaddr;
|
||||
if ( dstname != "" )
|
||||
c$socks$bound_name = dstname;
|
||||
|
||||
c$socks$bound_p = p;
|
||||
}
|
||||
|
||||
event socks_reply(c: connection, version: count, reply: count, dstaddr: addr, dstname: string, p: port) &priority=-5
|
||||
{
|
||||
Log::write(SOCKS::LOG, c$socks);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue