在 CentOS 7 上使用 IPv6 获取 Squid 和 TPROXY

Jam*_*ite 18 routing ipv6 squid transparent-proxy centos7

我在 CentOS 7 服务器上让 TPROXY 与 Squid 和 IPv6 一起工作时遇到问题。我以前使用 NAT 的通用拦截设置,但它仅限于 IPv4。我现在正在扩展设置以包含带有 TPROXY 的 IPv6。

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

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 的主要局域网3128

ip6tables -t mangle -I PREROUTING -p tcp --dport 80 -s "$OUTGOING_PROXY_IPV6" -j ACCEPT
Run Code Online (Sandbox Code Playgroud)

在 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
Run Code Online (Sandbox Code Playgroud)

squid.conf 配置为两个端口:

http_proxy 3128
http_proxy 3129 tproxy
Run Code Online (Sandbox Code Playgroud)

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

cache_peer localhost parent 8118 7 no-tproxy no-query no-digest
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

我不确定是否rp_filter需要修改,因为设置在 IPv4 上使用或不使用它们,并为 IPv6 产生相同的结果。

SELINUX

在 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;
Run Code Online (Sandbox Code Playgroud)

我还设置了以下布尔值:

setsebool squid_connect_any 1
setsebool squid_use_tproxy 1
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

小智 1

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

首先:test-ipv6.com 最近似乎对自己进行了一些更新,以便能够处理一种新型错误(今年早些时候就被破坏了)。再测试一下。

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

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

快速描述:

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

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

就我而言,我允许 ICMP 消息,但仍然存在问题。我还没有准备好认输并只是减少网络的 MTU(这是核心选项)。