Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixes #9 #14

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 57 additions & 6 deletions fatt.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
DISPLAY_FILTER = (
'tls.handshake.type == 1 || tls.handshake.type == 2 ||'
'ssh.message_code == 20 || ssh.protocol || rdp ||'
'gquic.tag == "CHLO" || http.request.method || data-text-lines'
'(quic && tls.handshake.type == 1) || gquic.tag == "CHLO" ||'
'http.request.method || data-text-lines'
)
DECODE_AS = {
'tcp.port==2222': 'ssh', 'tcp.port==3389': 'tpkt',
Expand Down Expand Up @@ -279,15 +280,15 @@ def process(self, packet):
self.logger.info(json.dumps(record))
return

# [ QUIC ]
elif (proto == 'GQUIC' or proto == 'QUIC') and\
('quic' in self.fingerprint or self.fingerprint == 'all'):
# [ GQUIC ]
elif proto == 'GQUIC' and ('gquic' in self.fingerprint or
self.fingerprint == 'all'):
if 'tag' in packet.gquic.field_names:
if packet.gquic.tag == 'CHLO':
record = self.client_gquic(packet)
# Print the result
if self.pout:
tmp = ('{sip}:{sp} -> {dip}:{dp} [QUIC] UAID="{ua}" SNI={sn} AEAD={ea} KEXS={kex}')
tmp = ('{sip}:{sp} -> {dip}:{dp} [GQUIC] UAID="{ua}" SNI={sn} AEAD={ea} KEXS={kex}')
tmp = tmp.format(
sip=record['sourceIp'],
sp=record['sourcePort'],
Expand All @@ -302,6 +303,29 @@ def process(self, packet):
if record and self.jlog:
self.logger.info(json.dumps(record))
return

# [ QUIC ]
elif proto == 'QUIC' and ('quic' in self.fingerprint or
self.fingerprint == 'all'):

if packet.quic.tls_handshake_type == '1':
record = self.client_quic(packet)

if self.pout:
tmp = ('{sip}:{sp} -> {dip}:{dp} [QUIC] serverName="{sn}" VER={ver}')
tmp = tmp.format(
sip=record['sourceIp'],
sp=record['sourcePort'],
dip=record['destinationIp'],
dp=record['destinationPort'],
ver=record['quic']['ver'],
sn=record['quic']['sni']
)
print(tmp)
if record and self.jlog:
self.logger.info(json.dumps(record))
return

return

def client_hassh(self, packet):
Expand Down Expand Up @@ -789,6 +813,33 @@ def server_http(self, packet):
}
return record

def client_quic(self, packet):

ver = sni = None
print(packet.quic.pretty_print())

if 'version' in packet.quic.field_names:
ver = packet.quic.version
if 'tls_handshake_extensions_server_name' in packet.quic.field_names:
sni = packet.quic.tls_handshake_extensions_server_name

sourceIp = packet.ipv6.src if 'ipv6' in packet else packet.ip.src
destinationIp = packet.ipv6.dst if 'ipv6' in packet else packet.ip.dst
record = {
"timestamp": packet.sniff_time.isoformat(),
"sourceIp": sourceIp,
"destinationIp": destinationIp,
"sourcePort": packet.udp.srcport,
"destinationPort": packet.udp.dstport,
"protocol": "quic",
"quic": {
"ver": ver,
"sni": sni
}
}
return record


def client_gquic(self, packet):
# https://tools.ietf.org/html/draft-ietf-quic-transport-20
sni = uaid = ver = stk = pdmd = ccs = ccrt = aead = scid = smhl = mids \
Expand Down Expand Up @@ -889,7 +940,7 @@ def parse_cmd_args():
'--fingerprint',
nargs='*',
default='all',
choices=['tls', 'ssh', 'rdp', 'http', 'gquic'],
choices=['tls', 'ssh', 'rdp', 'http', 'gquic', 'quic'],
help=helptxt)
helptxt = "a dictionary of {decode_criterion_string: decode_as_protocol} \
that is used to tell tshark to decode protocols in situations it \
Expand Down