-
Notifications
You must be signed in to change notification settings - Fork 19
/
egress.py
71 lines (54 loc) · 2.15 KB
/
egress.py
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
#!/usr/bin/env python2
"""TCP Packet egress reporter."""
from __future__ import print_function
import os
import logging
import netfilterqueue as nfq
from packets import IPPacket, TCPPacket, to_tuple
class PyWallEgress(object):
"""Egress monitoring process.
This class/process doesn't perform any packet filtering. It simply accepts
egress packets, and reports them to the Cracker if they are TCP.
"""
def __init__(self, mp_queue, queue_num=2):
"""Create the egress process.
Takes the mp_queue, which is where we report the TCP packets. queue-num
is the iptables queue to bind to.
"""
self.queue_num = queue_num
self.mp_queue = mp_queue
self._nfq_init = 'iptables -I OUTPUT -j NFQUEUE --queue-num %d'
self._nfq_close = 'iptables -D OUTPUT -j NFQUEUE --queue-num %d'
def run(self):
"""Run the egress process."""
# Create IPTables commands.
setup = self._nfq_init % self.queue_num
teardown = self._nfq_close % self.queue_num
# Set up IPTables to receive egress packets.
os.system(setup)
print('Set up IPTables: ' + setup)
# Create and run NFQ.
nfqueue = nfq.NetfilterQueue()
nfqueue.bind(self.queue_num, self.callback)
try:
nfqueue.run()
finally:
# Tear down IPTables rules.
os.system(teardown)
print('\nTore down IPTables: ' + teardown + '\n')
def callback(self, packet):
"""The callback called by IPTables for each egress packet."""
# Parse packet
ip_packet = IPPacket(packet.get_payload())
tcp_packet = ip_packet.get_payload()
logging.getLogger('pywall.egress').debug(unicode(ip_packet))
# Accept non-TCP packets.
if type(tcp_packet) is not TCPPacket:
packet.accept()
return
# Send the packet to the connection tracker.
tup = to_tuple(ip_packet, flip=True)
self.mp_queue.put((tup, bool(tcp_packet.flag_syn),
bool(tcp_packet.flag_ack),
bool(tcp_packet.flag_fin)))
packet.accept()