Scapy 如何通过 ppp link 发送数据包

How to send packet through ppp link by Scapy

我正在尝试通过 ppp link(由连接 3g 调制解调器的 wvdial 创建)发送数据包,但到目前为止失败了。这是我的 'ip addr' 打印输出:

22: ppp0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 3
    link/ppp
    inet 10.40.43.62 peer 10.64.64.64/32 scope global ppp0
       valid_lft forever preferred_lft forever*

这就是我尝试通过 Scapy 发送的方式:

[root@server1 ~]# scapy
INFO: Can't import matplotlib. Won't be able to plot.
INFO: Can't import PyX. Won't be able to use psdump() or pdfdump().
WARNING: No route found for IPv6 destination :: (no default route?)
INFO: Can't import python ecdsa lib. Disabled certificate manipulation tools
Welcome to Scapy (2.3.3)
>>> pkt=PPP()/IP(src="10.40.43.62", dst="8.8.8.8")/ICMP()/"1234567890"
>>> pkt.show()
###[ PPP Link Layer ]###
  proto= Internet Protocol version 4
###[ IP ]###
     version= 4
     ihl= None
     tos= 0x0
     len= None
     id= 1
     flags=
     frag= 0
     ttl= 64
     proto= icmp
     chksum= None
     src= 10.40.43.62
     dst= 8.8.8.8
     \options\
###[ ICMP ]###
        type= echo-request
        code= 0
        chksum= None
        id= 0x0
        seq= 0x0
###[ Raw ]###
           load= '1234567890'

>>> sendp(pkt, iface="ppp0")
.
Sent 1 packets.
>>> quit()

数据包捕获显示正在添加以太网层:

[root@server1 ~]# tshark -V -i ppp0 
Running as user "root" and group "root". This could be dangerous. Capturing on 'ppp0' Frame 1: 56 bytes on wire (448 bits), 56 bytes captured (448 bits) on interface 0
    Interface id: 0
    Encapsulation type: Linux cooked-mode capture (25)
    Arrival Time: Jan 29, 2018 10:54:20.793541000 BDT
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1517201660.793541000 seconds
    [Time delta from previous captured frame: 0.000000000 seconds]
    [Time delta from previous displayed frame: 0.000000000 seconds]
    [Time since reference or first frame: 0.000000000 seconds]
    Frame Number: 1
    Frame Length: 56 bytes (448 bits)
    Capture Length: 56 bytes (448 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: sll:eth:data] Linux cooked capture
    Packet type: Sent by us (4)
    Link-layer address type: 512
    Link-layer address length: 0
    Protocol: Ethernet (0x0003) Ethernet II, Src: EquipTra_00:40:01 (00:01:00:00:40:01), Dst: Semptian_00:00:26 (00:21:45:00:00:26)
    Destination: Semptian_00:00:26 (00:21:45:00:00:26)
        Address: Semptian_00:00:26 (00:21:45:00:00:26)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: EquipTra_00:40:01 (00:01:00:00:40:01)
        Address: EquipTra_00:40:01 (00:01:00:00:40:01)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Type: Unknown (0x3561) Data (26 bytes)

0000  0a 28 2b 3e 08 08 08 08 08 00 ed fa 00 00 00 00   .(+>............ 0010  31 32 33 34 35 36 37 38 39 30                   1234567890
    Data: 0a282b3e080808080800edfa000000003132333435363738...
    [Length: 26]

是 send/sendp/sr 是正确的命令,我在这里缺少什么?我可以通过 ppp 接口发送 ping,在数据包捕获中它显示为 ppp link 层。

这是从 ping 工具抓取的 scapy 特制数据包和普通 ICMP 数据包

正常:

12 <packet>
  <proto name="geninfo" pos="0" showname="General information" size="100">
    <field name="num" pos="0" show="13" showname="Number" value="d" size="100"/>
    <field name="len" pos="0" show="100" showname="Frame Length" value="64" size="100"/>
    <field name="caplen" pos="0" show="100" showname="Captured Length" value="64" size="100"/>
    <field name="timestamp" pos="0" show="Jan 31, 2018 00:47:08.960176000 BDT" showname="Captured Time" value="1517338028.960176000" size="100"/>
  </proto>
  <proto name="frame" showname="Frame 13: 100 bytes on wire (800 bits), 100 bytes captured (800 bits) on interface 0" size="100" pos="0">
    <field name="frame.interface_id" showname="Interface id: 0" size="0" pos="0" show="0"/>
    <field name="frame.encap_type" showname="Encapsulation type: Linux cooked-mode capture (25)" size="0" pos="0" show="25"/>
    <field name="frame.time" showname="Arrival Time: Jan 31, 2018 00:47:08.960176000 BDT" size="0" pos="0" show="Jan 31, 2018 00:47:08.960176000"/>
    <field name="frame.offset_shift" showname="Time shift for this packet: 0.000000000 seconds" size="0" pos="0" show="0.000000000"/>
    <field name="frame.time_epoch" showname="Epoch Time: 1517338028.960176000 seconds" size="0" pos="0" show="1517338028.960176000"/>
    <field name="frame.time_delta" showname="Time delta from previous captured frame: 50.679499000 seconds" size="0" pos="0" show="50.679499000"/>
    <field name="frame.time_delta_displayed" showname="Time delta from previous displayed frame: 50.679499000 seconds" size="0" pos="0" show="50.679499000"/>
    <field name="frame.time_relative" showname="Time since reference or first frame: 196.152414000 seconds" size="0" pos="0" show="196.152414000"/>
    <field name="frame.number" showname="Frame Number: 13" size="0" pos="0" show="13"/>
    <field name="frame.len" showname="Frame Length: 100 bytes (800 bits)" size="0" pos="0" show="100"/>
    <field name="frame.cap_len" showname="Capture Length: 100 bytes (800 bits)" size="0" pos="0" show="100"/>
    <field name="frame.marked" showname="Frame is marked: False" size="0" pos="0" show="0"/>
    <field name="frame.ignored" showname="Frame is ignored: False" size="0" pos="0" show="0"/>
    <field name="frame.protocols" showname="Protocols in frame: sll:ip:icmp:data" size="0" pos="0" show="sll:ip:icmp:data"/>
  </proto>
  <proto name="sll" showname="Linux cooked capture" size="16" pos="0">
    <field name="sll.pkttype" showname="Packet type: Sent by us (4)" size="2" pos="0" show="4" value="0004"/>
    <field name="sll.hatype" showname="Link-layer address type: 512" size="2" pos="2" show="512" value="0200"/>
    <field name="sll.halen" showname="Link-layer address length: 0" size="2" pos="4" show="0" value="0000"/>
    <field name="sll.etype" showname="Protocol: IP (0x0800)" size="2" pos="14" show="0x0800" value="0800"/>
  </proto>
  <proto name="ip" showname="Internet Protocol Version 4, Src: 10.93.65.103 (10.93.65.103), Dst: 8.8.8.8 (8.8.8.8)" size="20" pos="16">
    <field name="ip.version" showname="Version: 4" size="1" pos="16" show="4" value="45"/>
    <field name="ip.hdr_len" showname="Header length: 20 bytes" size="1" pos="16" show="20" value="45"/>
    <field name="ip.dsfield" showname="Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00: Not-ECT (Not ECN-Capable Transport))" size="1" pos="17" show="0" value="00">
      <field name="ip.dsfield.dscp" showname="0000 00.. = Differentiated Services Codepoint: Default (0x00)" size="1" pos="17" show="0x00" value="0" unmaskedvalue="00"/>
      <field name="ip.dsfield.ecn" showname=".... ..00 = Explicit Congestion Notification: Not-ECT (Not ECN-Capable Transport) (0x00)" size="1" pos="17" show="0x00" value="0" unmaskedvalue="00"/>
    </field>
    <field name="ip.len" showname="Total Length: 84" size="2" pos="18" show="84" value="0054"/>
    <field name="ip.id" showname="Identification: 0x0ea5 (3749)" size="2" pos="20" show="0x0ea5" value="0ea5"/>
    <field name="ip.flags" showname="Flags: 0x02 (Don&apos;t Fragment)" size="1" pos="22" show="0x02" value="40">
      <field name="ip.flags.rb" showname="0... .... = Reserved bit: Not set" size="1" pos="22" show="0" value="40"/>
      <field name="ip.flags.df" showname=".1.. .... = Don&apos;t fragment: Set" size="1" pos="22" show="1" value="40"/>
      <field name="ip.flags.mf" showname="..0. .... = More fragments: Not set" size="1" pos="22" show="0" value="40"/>
    </field>
    <field name="ip.frag_offset" showname="Fragment offset: 0" size="2" pos="22" show="0" value="4000"/>
    <field name="ip.ttl" showname="Time to live: 64" size="1" pos="24" show="64" value="40"/>
    <field name="ip.proto" showname="Protocol: ICMP (1)" size="1" pos="25" show="1" value="01"/>
    <field name="ip.checksum" showname="Header checksum: 0xd030 [correct]" size="2" pos="26" show="0xd030" value="d030">
      <field name="ip.checksum_good" showname="Good: True" size="2" pos="26" show="1" value="d030"/>
      <field name="ip.checksum_bad" showname="Bad: False" size="2" pos="26" show="0" value="d030"/>
    </field>
    <field name="ip.src" showname="Source: 10.93.65.103 (10.93.65.103)" size="4" pos="28" show="10.93.65.103" value="0a5d4167"/>
    <field name="ip.addr" showname="Source or Destination Address: 10.93.65.103 (10.93.65.103)" hide="yes" size="4" pos="28" show="10.93.65.103" value="0a5d4167"/>
    <field name="ip.src_host" showname="Source Host: 10.93.65.103" hide="yes" size="4" pos="28" show="10.93.65.103" value="0a5d4167"/>
    <field name="ip.host" showname="Source or Destination Host: 10.93.65.103" hide="yes" size="4" pos="28" show="10.93.65.103" value="0a5d4167"/>
    <field name="ip.dst" showname="Destination: 8.8.8.8 (8.8.8.8)" size="4" pos="32" show="8.8.8.8" value="08080808"/>
    <field name="ip.addr" showname="Source or Destination Address: 8.8.8.8 (8.8.8.8)" hide="yes" size="4" pos="32" show="8.8.8.8" value="08080808"/>
    <field name="ip.dst_host" showname="Destination Host: 8.8.8.8" hide="yes" size="4" pos="32" show="8.8.8.8" value="08080808"/>
    <field name="ip.host" showname="Source or Destination Host: 8.8.8.8" hide="yes" size="4" pos="32" show="8.8.8.8" value="08080808"/>
  </proto>
  <proto name="icmp" showname="Internet Control Message Protocol" size="64" pos="36">
    <field name="icmp.type" showname="Type: 8 (Echo (ping) request)" size="1" pos="36" show="8" value="08"/>
    <field name="icmp.code" showname="Code: 0" size="1" pos="37" show="0" value="00"/>
    <field name="icmp.checksum" showname="Checksum: 0x5b93 [correct]" size="2" pos="38" show="0x5b93" value="5b93"/>
    <field name="icmp.checksum_bad" showname="Bad Checksum: False" hide="yes" size="2" pos="38" show="0" value="5b93"/>
    <field name="icmp.ident" showname="Identifier (BE): 4058 (0x0fda)" size="2" pos="40" show="4058" value="0fda"/>
    <field name="icmp.ident" showname="Identifier (LE): 55823 (0xda0f)" size="2" pos="40" show="55823" value="0fda"/>
    <field name="icmp.seq" showname="Sequence number (BE): 1 (0x0001)" size="2" pos="42" show="1" value="0001"/>
    <field name="icmp.seq_le" showname="Sequence number (LE): 256 (0x0100)" size="2" pos="42" show="256" value="0001"/>
    <field name="icmp.data_time" showname="Timestamp from icmp data: Jan 31, 2018 00:47:08.000000000 BDT" size="8" pos="44" show="Jan 31, 2018 00:47:08.000000000" value="acbd705a00000000"/>
    <field name="icmp.data_time_relative" showname="Timestamp from icmp data (relative): 0.960176000 seconds" size="8" pos="44" show="0.960176000" value="acbd705a00000000"/>
    <field name="data" value="a2a60e0000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637">
      <field name="data.data" showname="Data: a2a60e0000000000101112131415161718191a1b1c1d1e1f..." size="48" pos="52" show="a2:a6:0e:00:00:00:00:00:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f:20:21:22:23:24:25:26:27:28:29:2a:2b:2c:2d:2e:2f:30:31:32:33:34:35:36:37" value="a2a60e0000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637"/>
      <field name="data.len" showname="Length: 48" size="0" pos="52" show="48"/>
    </field>
  </proto>
</packet>

Scapy 精心制作:

9 <packet>
  <proto name="geninfo" pos="0" showname="General information" size="54">
    <field name="num" pos="0" show="10" showname="Number" value="a" size="54"/>
    <field name="len" pos="0" show="54" showname="Frame Length" value="36" size="54"/>
    <field name="caplen" pos="0" show="54" showname="Captured Length" value="36" size="54"/>
    <field name="timestamp" pos="0" show="Jan 31, 2018 00:45:47.650839000 BDT" showname="Captured Time" value="1517337947.650839000" size="54"/>
  </proto>
  <proto name="frame" showname="Frame 10: 54 bytes on wire (432 bits), 54 bytes captured (432 bits) on interface 0" size="54" pos="0">
    <field name="frame.interface_id" showname="Interface id: 0" size="0" pos="0" show="0"/>
    <field name="frame.encap_type" showname="Encapsulation type: Linux cooked-mode capture (25)" size="0" pos="0" show="25"/>
    <field name="frame.time" showname="Arrival Time: Jan 31, 2018 00:45:47.650839000 BDT" size="0" pos="0" show="Jan 31, 2018 00:45:47.650839000"/>
    <field name="frame.offset_shift" showname="Time shift for this packet: 0.000000000 seconds" size="0" pos="0" show="0.000000000"/>
    <field name="frame.time_epoch" showname="Epoch Time: 1517337947.650839000 seconds" size="0" pos="0" show="1517337947.650839000"/>
    <field name="frame.time_delta" showname="Time delta from previous captured frame: 41.557182000 seconds" size="0" pos="0" show="41.557182000"/>
    <field name="frame.time_delta_displayed" showname="Time delta from previous displayed frame: 41.557182000 seconds" size="0" pos="0" show="41.557182000"/>
    <field name="frame.time_relative" showname="Time since reference or first frame: 114.843077000 seconds" size="0" pos="0" show="114.843077000"/>
    <field name="frame.number" showname="Frame Number: 10" size="0" pos="0" show="10"/>
    <field name="frame.len" showname="Frame Length: 54 bytes (432 bits)" size="0" pos="0" show="54"/>
    <field name="frame.cap_len" showname="Capture Length: 54 bytes (432 bits)" size="0" pos="0" show="54"/>
    <field name="frame.marked" showname="Frame is marked: False" size="0" pos="0" show="0"/>
    <field name="frame.ignored" showname="Frame is ignored: False" size="0" pos="0" show="0"/>
    <field name="frame.protocols" showname="Protocols in frame: sll:data" size="0" pos="0" show="sll:data"/>
  </proto>
  <proto name="sll" showname="Linux cooked capture" size="16" pos="0">
    <field name="sll.pkttype" showname="Packet type: Sent by us (4)" size="2" pos="0" show="4" value="0004"/>
    <field name="sll.hatype" showname="Link-layer address type: 512" size="2" pos="2" show="512" value="0200"/>
    <field name="sll.halen" showname="Link-layer address length: 0" size="2" pos="4" show="0" value="0000"/>
    <field name="sll.ltype" showname="Protocol: Unknown (0x0000)" size="2" pos="14" show="0x0000" value="0000"/>
  </proto>
  <proto name="fake-field-wrapper">
    <field name="data" value="0021450000240001000040011f050a5d4167080808080800272b000000003132333435363738">
      <field name="data.data" showname="Data: 0021450000240001000040011f050a5d4167080808080800..." size="38" pos="16" show="00:21:45:00:00:24:00:01:00:00:40:01:1f:05:0a:5d:41:67:08:08:08:08:08:00:27:2b:00:00:00:00:31:32:33:34:35:36:37:38" value="0021450000240001000040011f050a5d4167080808080800272b000000003132333435363738"/>
      <field name="data.len" showname="Length: 38" size="0" pos="16" show="38"/>
  </field>
</proto>
</packet>

你应该先用 Scapy 和 tshark 抓包,看看它们长什么样。然后,尝试模仿这个数据包,将其发回(首先,您可以尝试发送您收到的确切数据包),看看 tshark 是如何看待它的。

如果失败,一个选项是将 PPP 层留给主机的网络堆栈并使用 sr(IP()[...]) 而不是 srp(PPP()/IP()),看看是否可行。为此,您需要检查到您的 IP 目的地的路由是否使用 PPP 接口(使用 conf.route.route("[IP address]") 以确保)。

关于为什么sendp不起作用,我认为这可能是Scapy中的一个错误。如果您使用的是 Linux,您能否获得 current development version,应用以下补丁并重试?

diff --git a/scapy/arch/linux.py b/scapy/arch/linux.py
index b451fd15..4ad3c82f 100644
--- a/scapy/arch/linux.py
+++ b/scapy/arch/linux.py
@@ -491,7 +491,7 @@ class L3PacketSocket(SuperSocket):

 class L2Socket(SuperSocket):
     desc = "read/write packets at layer 2 using Linux PF_PACKET sockets"
-    def __init__(self, iface=None, type=ETH_P_ALL, promisc=None, filter=None, nofilter=0):
+    def __init__(self, iface=None, type=0, promisc=None, filter=None, nofilter=0):
         self.iface = conf.iface if iface is None else iface
         self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
         self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
@@ -555,7 +555,7 @@ class L2Socket(SuperSocket):

 class L2ListenSocket(SuperSocket):
     desc = "read packets at layer 2 using Linux PF_PACKET sockets"
-    def __init__(self, iface = None, type = ETH_P_ALL, promisc=None, filter=None, nofilter=0):
+    def __init__(self, iface=None, type=0, promisc=None, filter=None, nofilter=0):
         self.type = type
         self.outs = None
         self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))