Итак, после много исследований и тестирования других реализаций я, наконец, собрал версию, которая работает для меня. Он хранит списки MAC-адресов обоих интерфейсов и, следовательно, может препятствовать циклам. Также он быстрее других реализаций, поддерживая L2Socket и повторно используя его.
Существует еще много можно было бы настроить, но вот это:
#!/usr/bin/python2
import signal
from threading import Thread,Lock
from scapy.all import *
def usage():
print 'Usage: scapy_bridge.py host1_interface host2_interfcae'
print ''
print 'Example: sudo python scapy_bridge.py eth1 eth2'
print ' Sets up a bridge between the hosts connected on eth1 and eth2'
class Sniffer():
def __init__(self, input_interface, output_interface, sniffer_name):
self.input_interface = input_interface
self.output_interface = output_interface
self.sniffer_name = sniffer_name
self.output_socket = L2Socket(output_interface)
self.output_mac = get_if_hwaddr(self.output_interface)
def add_mac(self, list, mac):
if mac not in list:
list.append(mac)
def process_packet(self, pkt):
global macs_if1, macs_if2
handle_packet = True
if Ether in pkt:
src_mac = pkt[Ether].src
dst_mac = pkt[Ether].dst
if self.sniffer_name == '1to2':
if src_mac in macs_if2:
handle_packet = False
else:
self.add_mac(macs_if1, src_mac)
else:
if src_mac in macs_if1:
handle_packet = False
else:
self.add_mac(macs_if2, src_mac)
print 'MAC table 1: ' + str(macs_if1)
print 'MAC table 2: ' + str(macs_if2)
if handle_packet:
p = pkt.copy()
print 'MSGLEN=%d' % len(p)
if len(p) > 1400:
p.show()
frags = fragment(p)
for frag in frags:
self.output_socket.send(frag)
else:
self.output_socket.send(p)
def stopper_check(self, pkt):
return not still_running_lock.locked()
def sniffloop(self):
sniff(iface=self.input_interface, prn=self.process_packet, stop_filter=self.stopper_check)
# ==================================== MAIN
# global list of running threads
threads = []
# MAC table
macs_if1 = []
macs_if2 = []
# global lock to signal that we're still running
still_running_lock = Lock()
# catch Ctl-c and clean up threads
def signal_handler(signal, frame):
print 'Cleaning up sniff threads...'
still_running_lock.release()
try:
for t in threads: t.join()
except:
pass
print 'exiting.'
sys.exit(0)
if __name__ == '__main__':
if '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) != 3:
usage()
sys.exit(-1)
(host1_interface, host2_interface) = sys.argv[1:]
sniffer1 = Sniffer(host1_interface, host2_interface, '1to2')
sniffer2 = Sniffer(host2_interface, host1_interface, '2to1')
threads.append(Thread(target=sniffer1.sniffloop))
threads.append(Thread(target=sniffer2.sniffloop))
# set our "state" to running by acquiring the lock
still_running_lock.acquire()
for t in threads: t.start()
signal.signal(signal.SIGINT, signal_handler)
signal.pause()
EDIT: Я хотел бы добавить, что если вы хотите возиться с пакетами, mitmproxy в прозрачном режиме вместе с iptables, кажется, идеальное решение, которое также не требует настройки на стороне клиента. (т. е. прозрачно)
Я нашел это и попытался настроить переадресацию, но это не сработало. Есть ли пример? Нужно ли отключать обработку пакетов ядра, чтобы не мешать моей? –
@PhilippF Я добавил несколько примеров. –
Я пробовал все ссылки раньше. Никто из них не работал для меня. Кажется, это мешает обработке пакетов ядра. –