import sys
sys.path.append(r'/usr/local/lib/python2.6/site-packages')
import nfqueue
import time
from socket import AF_INET, AF_INET6, inet_ntoa, inet_aton
from dpkt import ip, tcp, hexdump
import re
import sys
import random
svr_ip=sys.argv[1]
my_ip=sys.argv[2]
def parse():
for r in sys.argv[3].split('.'):
if '-' in r: #xxx-yyy
m=re.match(r'(\d+)-(\d+)', r)
yield range(int(m.group(1)), int(m.group(2))+1)
else: #xxx
yield range(int(r), int(r)+1)
fake_ip_range=list(parse())
def get_fake_ip():
ip = '.'.join(str(random.choice(r)) for r in fake_ip_range)
print 'fake ip: ', ip
return ip
#Track connection by src port. This is very crude. Should watch tcp more closely.
port2ip={}
time0 = None
def cb(i,payload):
global time0
data = payload.get_data()
pkt = ip.IP(data)
if not time0:
time0=time.time()
print time.time()-time0,\
"source: %s" % inet_ntoa(pkt.src),\
"dest: %s" % inet_ntoa(pkt.dst)
if pkt.p == ip.IP_PROTO_TCP:
#outgoing to target server
if inet_ntoa(pkt.dst) == svr_ip:
if pkt.tcp.sport in port2ip:
pkt.src = port2ip[pkt.tcp.sport]
else:
fip = inet_aton(get_fake_ip())
port2ip[pkt.tcp.sport]=fip
pkt.src = fip
#incoming from target server
elif inet_ntoa(pkt.src) == svr_ip and \
inet_ntoa(pkt.dst) != my_ip:
#a stronger condition is to check if it is one of our fake ip
pkt.dst = inet_aton(my_ip)
pkt.tcp.sum = 0
pkt.sum = 0
payload.set_verdict_modified(
nfqueue.NF_ACCEPT,str(pkt),len(pkt))
return 0
payload.set_verdict(nfqueue.NF_ACCEPT)
sys.stdout.flush()
return 1
def run(cmd):
from commands import getstatusoutput
(s, o) = getstatusoutput(cmd)
print cmd
print 'exit code ', s
if len(o):
print o
cmds = [
#intercept outgoing packets
"iptables -t mangle -A POSTROUTING -p tcp -d %s -j NFQUEUE" % svr_ip,
#intercept incoming packets
"iptables -t mangle -A PREROUTING -p tcp -s %s -j NFQUEUE" % svr_ip,
#"iptables -A INPUT -p tcp -i eth1 -j NFQUEUE "
]
for c in cmds:
run(c)
q = nfqueue.queue()
print "open"
q.open()
print "bind"
q.bind(AF_INET);
print "setting callback"
q.set_callback(cb)
print "creating queue"
q.create_queue(0)
print "trying to run"
try:
q.try_run()
except KeyboardInterrupt, e:
print "interrupted"
print "unbind"
q.unbind(AF_INET)
print "close"
q.close()
for c in cmds:
run(c.replace('-A', '-D'))