![使用 IP 表进行 URL 过滤](https://linux22.com/image/127943/%E4%BD%BF%E7%94%A8%20IP%20%E8%A1%A8%E8%BF%9B%E8%A1%8C%20URL%20%E8%BF%87%E6%BB%A4.png)
我一直在尝试使用Iptables
.我设置了两个接口。流量从一个接口流入,从另一个接口流出。
以下是Iptables
我已经配置的:
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:TCPFILTER - [0:0]
:URLFILTER - [0:0]
#######################
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type any -j ACCEPT
-A INPUT -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT
#BGP
-A INPUT -p tcp -m state --state NEW -m tcp --dport 179 -j ACCEPT
# Pass traffic to filters which have TCP Flags PSH,ACK and DST Port 80
-A FORWARD -p tcp --tcp-flags PSH,ACK PSH,ACK --dport 80 -j TCPFILTER
-A FORWARD -p tcp --dport 80 -j TCPFILTER
-A FORWARD -j ACCEPT
# Further process only packets with HTTP Get Request
-A TCPFILTER -m string --string "GET /" --algo bm --from 1 --to 70 -j URLFILTER
-A TCPFILTER -j ACCEPT
-A URLFILTER -m string --algo bm --to 500 --string "Host: www.tutorialspoint.com" -p tcp -j REJECT --reject-with tcp-reset
-A URLFILTER -j ACCEPT
COMMIT
根据收到的数据包的 Wireshark 输出如下所示
我相信它应该有效,但我没有在链上得到任何点击,URLFILTER
如下所示:
# iptables -L -v -n
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
7 352 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 icmp type 255
108 6621 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state NEW,RELATED,ESTABLISHED
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:2002
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:179
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
39 34674 TCPFILTER tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 flags:0x18/0x18
253 13392 TCPFILTER tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT 75 packets, 13141 bytes)
pkts bytes target prot opt in out source destination
Chain TCPFILTER (2 references)
pkts bytes target prot opt in out source destination
0 0 URLFILTER all -- * * 0.0.0.0/0 0.0.0.0/0 STRING match "GET /" ALGO name bm FROM 1 TO 70
292 48066 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0
Chain URLFILTER (1 references)
pkts bytes target prot opt in out source destination
0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 STRING match "Host: www.tutorialspoint.com" ALGO name bm TO 500 reject-with tcp-reset
0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0
流量被接受并传递到TCPFILTER
但无法与GET /
字符串匹配。
任何帮助将不胜感激。
答案1
我找到了这不起作用的原因。
您不能依赖 netfilter 检查单个数据包上的整个 HTTP 请求。同一数据包不会匹配“GET /”和“Host:*”,因为该有效负载通过多个数据包传播。
考虑以下规则列表:
-A OUTPUT -p tcp -m tcp --dport 80 -j URLFILTER # would be FORWARD in your case
-A URLFILTER -m string --string "Host: www.kernel.org" --algo bm --from 1 --to 500 --icase -j LOG --log-prefix UF_MATCHHOST
-A URLFILTER -m string --string "GET /" --algo bm --from 1 --to 500 --icase -j LOG --log-prefix UF_MATCHGET
像这样对 www.kernel.org 的 HTTP 调用
GET / HTTP/1.0
Host: www.kernel.org
将以相反的顺序匹配两条规则,证明 URLFILTER 链被多个数据包遍历;第一个携带 GET 字符串,第二个携带主机字符串。因此,如果不进行进一步的工作,您就无法同时匹配 GET 和 Host。
[471493.767020] UF_MATCHGETIN= OUT=enp0s31f6 SRC=192.168.20.204 DST=147.75.205.195 LEN=67 TOS=0x00 PREC=0x00 TTL=64 ID=65494 DF PROTO=TCP SPT=51624 DPT=80 WINDOW=229 RES=0x00 ACK PSH URGP=0
[471499.761216] UF_MATCHHOSTIN= OUT=enp0s31f6 SRC=192.168.20.204 DST=147.75.205.195 LEN=73 TOS=0x00 PREC=0x00 TTL=64 ID=65495 DF PROTO=TCP SPT=51624 DPT=80 WINDOW=229 RES=0x00 ACK PSH URGP=0
也许您可以跟踪与 GET / 匹配的每个连接并匹配以下数据包,我认为这是可能的。
Netfilter 可以为您做到这一点,但它远不是完成这项工作的最佳工具。
原答案:
你的
-A TCPFILTER -m string --string "GET /" --algo bm --from 1 --to 70 -j URLFILTER
条目不匹配,您确定可以将字符串与原始 HTTP 流量进行匹配吗?您可以使用 tcpdump -vv 看到该字符串吗?你可以尝试一个更简单的匹配,看看是否有效?
您显示的wireshark输出是解析后的数据包,而不是iptables所看到的。您想要查看数据包的十六进制/ascii 有效负载以进行双重检查。