2015-10-16 4 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() 

EDIT: Я хотел бы добавить, что если вы хотите возиться с пакетами, mitmproxy в прозрачном режиме вместе с iptables, кажется, идеальное решение, которое также не требует настройки на стороне клиента. (т. е. прозрачно)

0

У Python есть библиотека scapy (доступна как python-scapy на Debian & Ubuntu), которая может облегчить извлечение, обработку и повторный ввод низкоуровневых сетевых данных.

Здесь у вас есть простой пример, который пересылает все данные с интерфейса на другой, изменяя 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) 

Вы можете увидеть больше примеров here, here или here.

+0

Я нашел это и попытался настроить переадресацию, но это не сработало. Есть ли пример? Нужно ли отключать обработку пакетов ядра, чтобы не мешать моей? –

+0

@PhilippF Я добавил несколько примеров. –

+0

Я пробовал все ссылки раньше. Никто из них не работал для меня. Кажется, это мешает обработке пакетов ядра. –

Смежные вопросы