Networking 软件IP转发

Networking 软件IP转发,networking,ip,Networking,Ip,在拦截和修改内容时,如何桥接两个不同的网络接口(例如eth0和wlan0) 请让我知道是否有很好的库或工具来做这件事。如果没有人在Python或C++中怎么做?我希望尽可能高层次地这样做 有人能提供一个简单的工作示例吗?Python有一个库(在Debian和Ubuntu上作为Python scapy提供),它可以简化底层网络数据的检索、处理和重新注入 这里有一个简单的示例,它将所有数据从一个接口转发到另一个接口,修改HTTP GET请求以指向example.com域 #!/usr/bin/env

在拦截和修改内容时,如何桥接两个不同的网络接口(例如eth0和wlan0)

请让我知道是否有很好的库或工具来做这件事。如果没有人在Python或C++中怎么做?我希望尽可能高层次地这样做

有人能提供一个简单的工作示例吗?

Python有一个库(在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)

您可以看到更多的示例,或者。

因此,经过大量研究和尝试其他实现,我最终组装了一个适合我的版本。 它保留两个接口的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似乎是一个完美的解决方案,它也不需要任何客户端配置。(即,它是透明的)

我找到了它,并尝试设置转发,但没有成功。有没有一个例子?我需要禁用内核数据包处理才能不干扰我的吗?@PhilippF我添加了一些示例。我以前尝试过所有链接。他们都不为我工作。它似乎会干扰内核数据包处理。您需要确保接口处于混杂模式,并且其中一个网络上的数据包除了网桥之外没有任何网关,以便所有数据包都到达它。