在 CentOS 7 上让 Squid 和 TPROXY 与 IPv6 一起工作

在 CentOS 7 上让 Squid 和 TPROXY 与 IPv6 一起工作

我在 CentOS 7 服务器上无法让 TPROXY 与 Squid 和 IPv6 协同工作。我之前使用过带有 NAT 的通用拦截设置,但仅限于 IPv4。我现在正在扩展设置以使用 TPROXY 包含 IPv6。

我一直在使用有关该主题的官方 Squid 维基文章来配置所有内容:

http://wiki.squid-cache.org/Features/Tproxy4

到目前为止,TPROXY 配置似乎在 IPv4 上工作正常,没有任何问题。但是对于 IPv6,连接会超时并且无法正常工作。我将分解设置以便更好地理解。

请注意,所有防火墙和路由规则对于 IPv4 来说都是完全相同的,唯一的区别是inet6ip6tables下面的示例中配置基于 IPv6 的规则。

  • 操作系统和内核:CentOS 7(3.10.0-229.14.1.el7.x86_64)
  • 根据 yum,所有软件包都是最新的
  • Squid 版本:3.3.8(也尝试过 3.5.9)
  • 防火墙:iptables/ip6tables 1.4.21
  • libcap-2.22-8.el7.x86_64

IPv6 连接目前通过 Hurricane Electric 的 6in4 隧道进行,该隧道在 DD-WRT 路由器上配置,然后通过 将分配的前缀委托给客户端radvd。Squid 盒配置了几个静态 IPv6 地址。

Squid 盒位于其所服务的主 LAN 内。端口 80 上的流量被拦截的客户端(主要是无线客户端)通过我的 DD-WRT 路由器推送到 Squid 盒,并采用以下防火墙和路由规则,改编自 Policy Routing wiki 文章和 DD-WRT wiki

在将流量传递到 Squid 盒方面,这似乎工作正常。除了上述规则外,我还必须在 DD-WRT 路由器上添加一条额外规则,即针对 Squid 盒上配置的传出 IPv4 和 IPv6 地址添加一条例外规则,否则我会遇到疯狂的循环问题,并且所有客户端(包括使用 Squid 的主 LAN)的流量都会中断3128

ip6tables -t mangle -I PREROUTING -p tcp --dport 80 -s "$OUTGOING_PROXY_IPV6" -j ACCEPT

在 Squid 框上,我使用以下路由规则和 DIVERT 链来相应地处理流量。我需要添加其他规则,以防止在测试期间使用已存在的链出现任何错误。我的防火墙是CSF,我已将以下内容添加到csfpre.sh

ip -f inet6 route flush table 100
ip -f inet6 rule del fwmark 1 lookup 100

ip -f inet6 rule add fwmark 1 lookup 100
ip -f inet6 route add local default dev eno1 table 100

ip6tables -t mangle -F
ip6tables -t mangle -X
ip6tables -t mangle -N DIVERT

ip6tables -t mangle -A DIVERT -j MARK --set-mark 1
ip6tables -t mangle -A DIVERT -j ACCEPT
ip6tables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
ip6tables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 3129

squid.conf配置为两个端口:

http_proxy 3128
http_proxy 3129 tproxy

此外,我也在使用 Privoxy,并且必须将其添加no-tproxy到我的 cache_peer 行,否则所有流量都无法转发到这两种协议。

cache_peer localhost parent 8118 7 no-tproxy no-query no-digest

tcp_outgoing_address由于 Privoxy,我没有使用任何指令,而是通过 CentOS 和绑定顺序来控制出站地址。

sysctl 值:

net.ipv4.ip_forward = 1
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.eno1.rp_filter = 0

我不确定是否rp_filter需要进行修改,因为无论有没有修改,该设置在 IPv4 上都能正常工作,并且对 IPv6 产生相同的结果。

系统管理软件

Squid 机器上启用了 SELINUX,但策略已配置为允许 TPROXY 设置,因此它不会被阻止(IPv4 工作无论如何都会显示这一点)。我已检查并grep squid /var/log/audit/audit.log | audit2allow -a得到<no matches>

#============= squid_t ==============

#!!!! This avc is allowed in the current policy
allow squid_t self:capability net_admin;

#!!!! This avc is allowed in the current policy
allow squid_t self:capability2 block_suspend;

#!!!! This avc is allowed in the current policy
allow squid_t unreserved_port_t:tcp_socket name_connect;

我还设置了以下布尔值:

setsebool squid_connect_any 1
setsebool squid_use_tproxy 1

IPv6 连接中断

最终,TPROXY 客户端的 IPv6 连接完全中断(3128使用 WPAD/PAC 文件的端口上的 LAN 客户端具有完全正常工作的 IPv6)。虽然看起来流量正在以某种方式路由到 Squid 框,但 TPROXY 上的 IPv6 请求并未出现在 中access.log。所有 IPv6 请求(文字 IPv6 和 DNS)都超时。我可以访问内部 IPv6 客户端,但同样,此流量也没有被记录。

我使用 test-ipv6.com 进行了一些测试,发现它检测到了我的传出 Squid IPv6 地址,但 IPv6 测试显示为坏/慢或超时。我暂时启用了 via 标头,发现 Squid HTTP 标头可见,因此流量至少到达了 Squid 框,但到达那里后没有被正确路由。

我已经尝试让它工作了一段时间,但找不到问题所在,我甚至在 Squid 邮件列表上询问过,但无法诊断实际问题或解决它。根据我的测试,我很确定它位于以下区域之一,并且 Squid 框是问题所在:

  • 路由
  • 核心
  • 防火墙

任何能让 TPROXY 和 IPv6 正常工作的想法和其他步骤我都将不胜感激!

附加信息

ip6tables 规则:

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DIVERT     tcp      ::/0                 ::/0                 socket
TPROXY     tcp      ::/0                 ::/0                 tcp dpt:80 TPROXY redirect :::3129 mark 0x1/0x1

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination

Chain DIVERT (1 references)
target     prot opt source               destination
MARK       all      ::/0                 ::/0                 MARK set 0x1
ACCEPT     all      ::/0                 ::/0

IPv6 路由表(前缀隐藏)

unreachable ::/96 dev lo  metric 1024  error -101
unreachable ::ffff:0.0.0.0/96 dev lo  metric 1024  error -101
2001:470:xxxx:xxx::5 dev eno1  metric 0
    cache  mtu 1480
2001:470:xxxx:xxx:b451:9577:fb7d:6f2d dev eno1  metric 0
    cache
2001:470:xxxx:xxx::/64 dev eno1  proto kernel  metric 256
unreachable 2002:a00::/24 dev lo  metric 1024  error -101
unreachable 2002:7f00::/24 dev lo  metric 1024  error -101
unreachable 2002:a9fe::/32 dev lo  metric 1024  error -101
unreachable 2002:ac10::/28 dev lo  metric 1024  error -101
unreachable 2002:c0a8::/32 dev lo  metric 1024  error -101
unreachable 2002:e000::/19 dev lo  metric 1024  error -101
unreachable 3ffe:ffff::/32 dev lo  metric 1024  error -101
fe80::/64 dev eno1  proto kernel  metric 256
default via 2001:470:xxxx:xxxx::1 dev eno1  metric 1

答案1

我意识到这已经很老了,我自己也没有完整的答案,但是,我正在做的事情与你非常相似,并且有几乎相同的症状。

首先:test-ipv6.com 似乎最近进行了更新,以便能够处理一种新型错误(今年早些时候出现过故障)。再测试一下。

就我的情况来说,它向我发送了一个 URL,其中描述了我似乎遇到的一个问题: 路径 MTU 检测常见问题解答。他们提供了一个 URL,您可以使用 cURL 进行 PMTUD 测试,然后您可以使用tpcdump或 wireshark 检查您的流量。

当流量通过 Squid 进行 TPROXY 处理时,IPv6 路径 MTU 检测无法完全在您的主机上工作。(我仍在研究为什么它无法在我的主持人,所以我没有明确的解决方案)。

简要描述:

  • ICMP 在 IPv6 中极其重要。许多人想阻止 ICMP,但结果弊大于利。
  • 如果数据包对于您的连接来说“太大”,则该数据包将被丢弃,并且应该向原始服务器发送 ICMP 类型 2(“数据包太大”)消息,要求其减小数据包大小并重新发送。
  • 如果 ICMP 消息没有到达服务器,服务器将继续重新发送大数据包——该数据包会因为太大而被立即丢弃。
  • 这被描述为“黑洞”因为数据包永远无法到达目的地。

因此您可能需要确保您的防火墙规则设置为接受 ICMPv6 消息(请参阅 RFC4890 以获取“所需”ICMP 类型的列表)。

就我的情况而言,我允许 ICMP 消息,但问题仍然存在。我还没准备好放弃,只是降低网络的 MTU(这是最根本的选择)。

相关内容