python中的BPF,用于嗅探多个TCP端口的数据包

2024-09-29 17:21:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我从http://allanrbo.blogspot.in/2011/12/raw-sockets-with-bpf-in-python.html得到代码。它工作得很好,但是我想嗅探多个TCP端口上的流量,比如端口90008022。。。在

所以我修改了filter_list式的打击

filters_list = [  
    # Must have dst port 67. Load (BPF_LD) a half word value (BPF_H) in   
    # ethernet frame at absolute byte offset 36 (BPF_ABS). If value is equal to  
    # 67 then do not jump, else jump 5 statements.  
    bpf_stmt(BPF_LD | BPF_H | BPF_ABS, 36),  
    bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 9000, 0, 5), <===== Here I added another port
    bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 80, 0, 5),


    # Must be UDP (check protocol field at byte offset 23)  
    bpf_stmt(BPF_LD | BPF_B | BPF_ABS, 23),   
    bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 0x06, 0, 3), #<==Changed for TCP "0x06"

    # Must be IPv4 (check ethertype field at byte offset 12)  
    bpf_stmt(BPF_LD | BPF_H | BPF_ABS, 12),   
    bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 0x0800, 0, 1),  

    bpf_stmt(BPF_RET | BPF_K, 0x0fffffff), # pass  
    bpf_stmt(BPF_RET | BPF_K, 0), # reject   ]

问题是,有时它是有效的,有时它不工作,比如只在9000而不是80获得流量,有时在80得到流量。我没有完全理解代码。有什么帮助吗?在


Tags: 代码inabsbyteat流量offsetld
2条回答

我知道你想给你的原始套接字附加一个过滤器,这是我最近的工作。多亏了几个星期的努力工作,我找到了一个简单的方法把过滤器连接到一个原始插座上。我想与您分享:)
首先确保您已经安装了tcpdump(这是一个Linux系统管理器工具),如果您的平台是Linux中的发行版之一,让我们进入下一步。
其次,您需要拥有sudo or root权限才能执行该工具。
第三步,以演示为例,更改它以适合您的情况。在

$ sudo tcpdump -i enp4s0 -dd 'tcp and (port 9000 or port 80 or port 22)'  

让我先解释一下参数。
tcpdump>;在网络上转储流量
-i>;指定接口
enp4s0>;网络接口
-dd>;将包匹配代码作为C程序片段转储。
tcp and (port 9000 or port 80 or port 22)>;伯克利包过滤器(BPF)语法

执行此命令后,您应该生成如下所示的代码:

^{pr2}$

看起来一团糟,但别担心,让我们继续勇敢吧。在

先让我弄清楚它是什么,这是一个包过滤代码,如果你以前已经学过汇编语言,你会觉得很熟悉的。在

第二,因为它是C风格的代码,它不适合我们的python用法,所以我们需要对数据进行润色,使用follow python代码

import subprocess

cmd = "sudo tcpdump -i enp4s0 -dd 'tcp and (port 9000 or port 80 or port 22)'"
tcpdumpBinary = subprocess.check_output(cmd, shell=True)
macroString = '( ' + tcpdumpBinary.decode('utf-8').replace(
            '\n', '').replace('{', '[').replace('}', ']') + ')'
macroString = eval(macroString)

第三,现在您可以使用macroStringfilters_list相同。在

这个方法帮助我摆脱了过滤代码的困境,希望对您有所帮助。在

据我所知,问题似乎来自前两个条件跳转的逻辑。具体来说:

bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 9000, 0, 5), # if false, skip 5 instructions
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 80, 0, 5),

指令bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, <val>, <jtrue>, <jfalse>)表示

^{pr2}$

所以这两条线的意思是:

if port is 9000
    then if port is 80
        then go on with checks…
    else skip 5 instructions (i.e. reject)
else
    skip 5 instructions (i.e. pass, as jump offset was not updated from 5 to 6)

你可能想要更像:

if port is 9000
    then go on with checks…
else
    if port is 80
        then go on with checks…
    else reject

我还没有测试过,但是为了得到这个逻辑,我想说你需要调整跳跃偏移,如下所示:

bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 9000, 1, 0), # if true skip 1 insn
                                                 # (i.e. port 80 check) else 0
                                                 # and check for port 80
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 80, 0, 5),   # if true skip 0 else skip 5
                                                 # (and land on “reject”)

编辑1:然后过滤三个端口,将变成:

bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 8084, 2, 0), # skip the next 2 checks if true
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 9000, 1, 0), # skip the next check if true
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 22,   0, 5), # if true go on else reject

编辑2:若要在源端口(除了目标端口)上也进行筛选,您可以尝试这样的方法(我这边还没有测试):

# Load TCP src port into register K, and check port value
# For packets with IP header len == 20 bytes, TCP src port should be at offset 34
# We adapt the jump offsets to go to next check if no match (or to “reject” after
# the last check), or to skip all remaining checks on ports if a match is found.
bpf_stmt(BPF_LD | BPF_H | BPF_ABS, 34),           # 34 == offset of src port
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 8084, 6, 0),
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 9000, 5, 0),
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 22,   4, 0),

# As before: if no match on src port, check on dst port
bpf_stmt(BPF_LD | BPF_H | BPF_ABS, 36),
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 8084, 2, 0),
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 9000, 1, 0),
bpf_jump(BPF_JMP | BPF_JEQ | BPF_K, 22,   0, 5),

…

相关问题 更多 >

    热门问题