【问题标题】:Modification of HTTP headers with netfilterqueue and scapy使用 netfilterqueue 和 scapy 修改 HTTP 标头
【发布时间】:2016-07-30 05:11:28
【问题描述】:

我想使用 netfilterqueue(0.6 - 最新)和 scapy 用我的值更改“主机”标头。这是我的 iptables 规则:

iptables -A OUTPUT -p tcp --dport 80 -j NFQUEUE --queue-num 0

我有我的代码:

from netfilterqueue import *
from scapy.all import *

def change(pkt):
    scapy_pkt = IP(pkt.get_payload())
    if scapy_pkt.haslayer(TCP) and scapy_pkt.getlayer(TCP).dport == 80 and scapy_pkt.haslayer(Raw):
        http_content = scapy_pkt.getlayer(Raw).load
        list_of_headers = http_content.split("\r\n")
        new_headers = []
        for i in list_of_headers:
            if "Host" in i:
                new_headers.append("Host: google.pl")
            else:
                new_headers.append(i)

        pkt.set_payload("\r\n".join(new_headers))

    pkt.accept()

nfqueue = NetfilterQueue()
nfqueue.bind(0, change)
try:
    nfqueue.run()
except KeyboardInterrupt:
    print

但它不起作用..我不知道为什么.. 我在更改之前和之后打印标题,唯一的更改是“主机”标题。 Soo..为什么它不起作用?有人有什么想法吗? :)

我使用 CURL 进行测试,使用wireshark 进行调试。请求未发送。我在wireshark中找不到。

编辑: 我试图解决这个问题,我将代码更改为:

from netfilterqueue import *
from scapy.all import *

def change(pkt):
    scapy_pkt = IP(pkt.get_payload())
    print dir(pkt);
    if scapy_pkt.haslayer(TCP) and scapy_pkt.getlayer(TCP).dport == 80 and scapy_pkt.haslayer(Raw):
        #http_content = scapy_pkt.getlayer(Raw).load
        #list_of_headers = http_content.split("\r\n")
        #new_headers = []
        #for i in list_of_headers:
        #   if "Host" in i:
        #       new_headers.append("Host: google.pl")
        #   else:
        #       new_headers.append(i)

        scapy_pkt.dst = 'google.pl'

        del scapy_pkt[IP].chksum
        del scapy_pkt[TCP].chksum
        pkt.set_payload(str(scapy_pkt))
    pkt.accept()

nfqueue = NetfilterQueue()
nfqueue.bind(0, change)
try:
    nfqueue.run()
except KeyboardInterrupt:
    print

但它仍然无法正常工作。在 Wireshark 中,我使用 HTTP 进行过滤。但是当我通过 TCP 和 destport == 80 进行过滤时,我可以看到包,但目标是从传递给 CURL 的参数到 IP,而不是我在上面的代码中注入数据包的 IP。

感谢您的提前:)

【问题讨论】:

    标签: python http tcp scapy


    【解决方案1】:

    这里有几个问题。

    [更新:PyPI 的最新版本 0.3 已过时,正如评论中指出的那样。 0.6 版确实实现了.set_payload()] 首先,您要使用的库似乎没有实现.set_payload() 来更改数据包(请参阅here)。您可能想改用nfqueue-bindings

    首先(与您的第一次尝试有关),如果您必须更改数据的 长度,更改 TCP 有效负载很困难(这里就是这种情况,因为您尝试添加 HTTP 标头),因为您必须更改同一连接中其他数据包的序列号和确认号。

    要实现这一点,您有两种选择:

    • 使用透明的 HTTP 代理,它将修改或添加您想要的标头,并将您想要篡改的连接重定向到代理。
    • 确保您所做的更改将保留数据的大小(例如,将标题替换为另一个标题,并注意长度)。

    第二次(与您的第二次尝试有关),scapy_pkt.dst = 'google.pl' 设置 IP 层的目标(并且不更改数据),IP 目标 NAT 也是如此。这是非常不同的,应该更容易做到(这里不要弄乱序列/确认号),但您必须在以下位置进行相同的修改:

    • 接收到的数据包不包含数据(您的代码仅更改带有 TCP 有效负载的数据包,因此保留 SYN+ACK,例如未修改数据包)。
    • 您收到的数据包(您还需要一个 INPUT iptables 规则)。

    【讨论】:

    • 您好,感谢您的回复。 Soo .. 我使用的这个库已经实现了 set_payload() - 我使用的是 0.6 版本,你提供了 0.3 版本的链接。嗯..所以这并不像我想的那么简单..你能看看我传入的数据修改 - pastebin.com/u0F6YeCB 吗?
    • 我已经更新了您评论第一部分的答案。您在 pastebin 上的代码尝试修复 Content-Length HTTP 标头的值(如果您更改 HTTP 数据长度,而不是 HTTP 标头,则需要此值),但您仍然遇到 TCP 序列/确认号的问题,这将在这个数据包之后是错误的。我认为答案中列出了更简单的选项(保留 TCP 数据长度,或使用透明的 HTTP 代理)。
    • 好吧,我想我对 TCP 的理解不够……序列号是 TCP 对话中的数据包数。当我改变一个数据包的顺序时,我应该在这个“谈话”中修改其他数据包吗?什么是 ACK?
    • 这是一个很长的答案。也许this article can be a good start
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-27
    • 1970-01-01
    • 2011-03-22
    • 1970-01-01
    相关资源
    最近更新 更多