处理原始数据包以具有 NAT 功能

Manipulating raw packets to have NAT functionality

我想在 python 中实现自定义 NAT,为此我想接收所有客户端数据包并修改它们。然后将它们转发到另一台设备。

我发现 scapy 可以轻松处理和发送数据包。但是找不到接收数据包的方法。那么是否可以接收数据包然后像编辑 source IPdestination IP 一样编辑它们并读取 UDP headers 并转发它们然后转发响应数据包?

也可以使用scapysniff()函数接收数据包:

>>> help(sniff)
Sniff packets and return a list of packets.
Args:
    count: number of packets to capture. 0 means infinity.
    store: whether to store sniffed packets or discard them
    prn: function to apply to each packet. If something is returned, it
         is displayed.
         --Ex: prn = lambda x: x.summary()
    filter: BPF filter to apply.
    lfilter: Python function applied to each packet to determine if
             further action may be done.
             --Ex: lfilter = lambda x: x.haslayer(Padding)
    offline: PCAP file (or list of PCAP files) to read packets from,
             instead of sniffing them
    timeout: stop sniffing after a given time (default: None).
    L2socket: use the provided L2socket (default: use conf.L2listen).
    opened_socket: provide an object (or a list of objects) ready to use
                  .recv() on.
    stop_filter: Python function applied to each packet to determine if
                 we have to stop the capture after this packet.
                 --Ex: stop_filter = lambda x: x.haslayer(TCP)
    iface: interface or list of interfaces (default: None for sniffing
           on all interfaces).
    monitor: use monitor mode. May not be available on all OS
    started_callback: called as soon as the sniffer starts sniffing
                      (default: None).
The iface, offline and opened_socket parameters can be either an
element, a list of elements, or a dict object mapping an element to a
label (see examples below).
Examples:
  >>> sniff(filter="arp")
  >>> sniff(lfilter=lambda pkt: ARP in pkt)
  >>> sniff(iface="eth0", prn=Packet.summary)
  >>> sniff(iface=["eth0", "mon0"],
  ...       prn=lambda pkt: "%s: %s" % (pkt.sniffed_on,
  ...                                   pkt.summary()))
  >>> sniff(iface={"eth0": "Ethernet", "mon0": "Wifi"},
  ...       prn=lambda pkt: "%s: %s" % (pkt.sniffed_on,
  ...                                   pkt.summary()))

特别是 prn 参数,允许您对每个接收到的数据包执行操作。他们有很多很棒的教程

根据您的评论,这里有一个示例:

 def _process(pkt):
      if IP in pkt:
           pkt[IP].dst = "y.y.y.y"
           pkt[Ether].dst = None  # Force scapy to re-calculate the MAC dst
           sendp(pkt)  # send the packet
 sniff(iface="eth0", prn=_process)