这是我的网络配置:
我的网络配置http://daveden.files.wordpress.com/2013/05/network-configuration.png
代理服务器在端口 3128 上运行 Ubuntu,其中 Squid 在端口 8080 上运行,DansGuardian 在端口 8080 上运行。
我想强制所有客户端使用代理服务器(具体来说是端口 8080)进行任何 HTTP/HTTPS 访问。
但是,我不想透明地重定向,因为这不适用于 HTTPS。我不介意配置每个客户端,也不介意每个客户端都知道它正在使用代理服务器。我只是不希望客户端能够在没有代理设置的情况下上网。
我该怎么做?如果客户端未配置为使用端口 8080 上的代理服务器,我可以丢弃数据包吗?
我尝试使用 iptables 丢弃 dport 不是 8080 的数据包,但我认为拒绝了太多数据包,因此我无法再访问任何东西。
编辑
我重写了这个问题,使它不再是针对 iptables 的,但我并不反对使用 iptables。我只是想吸引更广泛的可能解决方案。
编辑2
我想我可能给一些人留下了错误的印象。需要澄清的是,我对过滤HTTPS 流量(即在代理处拆开数据包并检查内容)。我更感兴趣的是阻塞使用 DansGuardian 的网站,无论是通过 HTTP 还是 HTTPS(通过查看数据包的目的地)。
编辑3
根据 Alexandru-Florin Vintil 的以下建议,我目前正在做的事情如下:
# Redirect HTTP traffic to port 8080 (DansGuardian)
iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j REDIRECT --to-port 8080
# Check TCP and UDP traffic against whitelist
iptables -A FORWARD -i eth1 -p tcp --dport 443 -j whitelist
iptables -A FORWARD -i eth1 -p udp --dport 443 -j whitelist
# Drop all other HTTPS traffic
iptables -A FORWARD -i eth1 -p tcp --dport 443 -j DROP
iptables -A FORWARD -i eth1 -p udp --dport 443 -j DROP
# Drop all traffic aimed straight at the proxy
iptables -A FORWARD -i eth1 -p tcp --dport 3128 -j DROP
iptables -A FORWARD -i eth1 -p udp --dport 3128 -j DROP
iptables -A FORWARD -i eth1 -p tcp --dport 8080 -j DROP
iptables -A FORWARD -i eth1 -p udp --dport 8080 -j DROP
简而言之,将 HTTP 流量重定向到端口 8080,丢弃所有未列入白名单的 HTTPS 流量(在单独的链中),并丢弃所有明确使用代理的流量。如果没有最后一条规则,客户端只要将浏览器配置为使用代理,就可以使用 HTTPS 访问任何网站,因为目标端口是 8080 而不是 443。因此,即使丢弃所有绑定到 443 的流量也不会完全阻止 HTTPS。
答案1
我的看法:
关于 HTTP:使用防火墙透明地将端口 80 流量转发到代理/过滤器是最简单的方法。无需客户端配置,+ 您可以免除任何主机/子网使用代理,而无需重新配置客户端。这是您可以确保所有应该通过代理的内容都是正确的唯一方法。
除了阻止所有传出的 HTTPS 443 流量并仅允许基于允许传出端口 443 的 IP 的站点子集之外的任何方法都不会按预期工作。HTTPS 的安全协议旨在防止中间人攻击(代理是“合法”的 MITM)。这样,HTTPS 就可以做它设计的目的。但是,如果你想忽略HTTPS,您应该将 Squid 设置为使用 DIRECT 而不是使用 CONNECT(分接),但即使如此,您仍可能会遇到 HTTP/HTTPS 部分混合的问题网站。这样,您的 Squid 代理也将管理 HTTPS。这也应该反映在防火墙的透明转发部分。
答案2
当你发现某件应该起作用的事情没有起作用时,你需要问问自己,是否还有其他你没有注意到的因素。规则
sudo iptables -A INPUT -p tcp ! --dport 8080 -j REJECT
看起来应该可以工作,但是你有附加它会进入 INPUT 链,因此很可能被链中的前一个规则所规避。此规则本身就足够了,因为 INPUT 链是传入数据包击中的第一个链。如果它们在 INPUT 链上被拒绝,它们就永远不会到达 FORWARD 或 OUTPUT 链。当然,此规则将阻止一切目的端口不是 8080 的 TCP,这可能不是您真正想要的,除非 8080 处的代理是机器上唯一的服务,并且您只从控制台登录。
因此,首先要做的是列出规则并寻找可能导致数据包通过的原因:
sudo iptables -L
如果您的防火墙是反向 NAT,那么您也应该列出 NAT 表。
sudo iptables -L -t nat
然后,尝试将相同的规则放在开始链的:
sudo iptables -I INPUT -p tcp ! --dport 8080 -j REJECT
看看这是否不能解决问题,或者至少让您更有信心了解iptables
工作原理,以便完成规则集。如果您正在远程处理此主机,我的建议将切断您的工作,因此您应该仅从控制台执行此操作。要安全地远程工作,请参阅我的同事Eli Rosencruft 关于远程调整防火墙的帖子。
答案3
标准
单独的(用户定义的)链可能会有帮助。
# create a chain just for user 100 (192.168.1.100)
iptables -N custom_user_100
# redirect all traffic FROM user 100 to custom chain
iptables -A INPUT -p tcp -s 192.168.1.100 -j custom_user_100
# return from user chain for valid traffic, drop all other
iptables -A custom_user_100 -p tcp --dport 8080 -j RETURN
iptables -A custom_user_100 -j DROP
因此,这样做的目的是将来自 192.168.1.100 的任何流量重定向到自定义链。此自定义(用户定义)链仅在找到有效匹配项(目的地为端口 8080 的流量)时返回。所有其他不匹配的流量(不会导致从链返回)都是已丢弃。
稍后您可以查看表统计信息来验证是否发生了这种情况:
iptables -L -v -n
转发
现在,如果您正在处理转发流量,那么将会有一组不同的规则 - 但使用自定义(用户定义)链的想法是相同的。我喜欢参考此链接中的图表:http://www.csie.ntu.edu.tw/~b93070/CNL/v4.0/CNLv4.0.files/Page697.htm尝试了解数据包的流动时。
在这种情况下,您可能需要执行以下操作:
# create a chain just for user 100 (192.168.1.100)
iptables -N custom_user_100
# redirect all traffic FROM user 100 to custom chain
iptables -A FORWARD -p tcp -s 192.168.1.100 -j custom_user_100
# return from user chain for valid traffic, drop all other
iptables -A custom_user_100 -p tcp --dport 8080 -j RETURN
iptables -A custom_user_100 -j DROP
这与第一个相同,只是应用于 INPUT 链的规则改为应用于 FORWARD 链。
更新 2013-05-24
我重读了你的问题。所以会重新开始。
假设您的“代理”实际上是一个路由器。也就是说,它将所有数据包从一个接口传递到另一个接口 - 可能使用 NAT。这意味着所有感兴趣的数据包都流经 FORWARD 链。
接下来:你说你将配置所有使用端口 8080 的客户端来访问代理本身。好的。这意味着所有那些数据包将通过 INPUT 链进入“代理”。
所以:您只是想阻止任何人从 FORWARD 链上的 8080 端口出去。
iptables -A FORWARD -p tcp --dport 8080 -j REJECT
此规则将确保转发到目标端口 8080 的任何内容都将被拒绝(ICMP 数据包将发送到试图通过代理传递数据包的客户端)。
实施此规则后,务必通过尝试建立此类禁止连接来测试这一点 - 然后通过键入以下内容列出规则:
iptables -L -v -n |grep 8080
并确保计数器已增加。如果没有,则路由器配置存在问题。
答案4
如果您不希望客户端在没有代理的情况下访问 http{s} 站点,那么您可以直接DROP
将REJECT
数据包转发到端口 80 和 443:
IPTABLES -I FORWARD -i eth1 -p tcp -m multiport --dports 80,443 -j REJECT
您的内部接口在哪里eth1
。这样您就不必与其他端口/访问打交道了。