2015-10-16 62 views
1

在拦截和修改内容时如何桥接两个不同的网络接口(例如eth0和wlan0)?软件IP转发

请让我知道是否有好的库或工具来做到这一点。如果没有人会在Python或C++中做到这一点?我想尽可能地做到这一点。

有人可以提供一个最小的工作示例?

回答

1

因此,经过大量的研究和尝试其他实现,我终于汇编了一个适合我的版本。 它保留了两个接口的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() 

编辑: 我想补充一点,如果你想惹的数据包,mitmproxy在透明模式与iptables一起似乎是一个完美的解决方案,它也不需要任何客户端配置。 (即它是透明的)

0

Python的scapy库(Debian & Ubuntu上的python-scapy可用)可以简化低级网络数据的检索,处理和重新注入。

这里有一个简单的例子,它将所有数据从接口转发到另一个接口,修改HTTP GET请求以指向example.com域。

#!/usr/bin/env python 

import scapy.all as scapy 
import re 

OWN_IP_ON_RECV_IFACE="192.168.1.128" 
RECV_IFACE="wlan0" 
SEND_IFACE="eth0" 

def modify_packet(packet): 
    # example 
    if packet.haslayer(scapy.TCP) and packet[scapy.TCP].dport == 80 and packet[TCP].payload: 
     data = str(packet[scapy.TCP].payload) 
     modified_data = re.sub("\r\nHost: .+\r\n", "\r\nHost: example.com\r\n", data) 
     packet[scapy.TCP].payload = modified_data 
     print "Packet modified!" 
    return packet 

def packet_received(packet): 
    if packet.haslayer(scapy.IP) and packet[scapy.IP].dst != OWN_IP_ON_RECV_IFACE and packet[scapy.IP].src != OWN_IP_ON_RECV_IFACE: 
     modified_packet = modify_packet(packet[scapy.IP]) 
     packet_to_send = scapy.Ether()/modified_packet 
     scapy.sendp(packet_to_send, iface=SEND_IFACE) 
     print "Packet sent" 

scapy.sniff(iface=RECV_IFACE, store=0, prn=packet_received) 

你可以看到更多的例子hereherehere

+0

我发现那个,并试图建立一个转发,但它没有工作。有没有例子?我是否需要禁用内核数据包处理来不干扰我的? –

+0

@PhilippF我添加了一些例子。 –

+0

我已经尝试过所有的链接。他们都没有为我工作。它似乎干扰内核数据包处理。 –