2015-10-16 23 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

我已經嘗試過所有的鏈接。他們都沒有爲我工作。它似乎干擾內核數據包處理。 –