用netfilterqueue和scapy修改HTTPheaders

Modification of HTTP headers with netfilterqueue and scapy

我想使用 netfilterqueue(0.6 - 最新)和 scapy 用我的值更改 "host" header。这是我的 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

但它不起作用..我不知道为什么.. 我在更改前后打印了 header,唯一的更改是 "Host" header。 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。

感谢提前:)

这里有几个问题。

[更新:PyPI 的最新版本 0.3 是评论中指出的 out-of-date。版本 0.6 确实 实现了 .set_payload()] 在任何事情之前,您要使用的库似乎没有实现 .set_payload() 来改变数据包(参见 here). You may want to use nfqueue-bindings 代替。

首先(与您的第一次尝试相关),如果您必须更改数据的 length(这里就是这种情况,因为您尝试添加 HTTP header),因为您必须更改同一连接中其他数据包的序列号和确认号。

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

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

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

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