让 Squid 使用 IPv6 /48 块通过隧道连接

让 Squid 使用 IPv6 /48 块通过隧道连接

我有一台运行 Squid 的 Ubuntu 14.05 服务器。它通过 Hurricane Electric 的服务建立了 IPv6 连接。我试图让服务器可以使用他们提供的 /48 中的所有 IP。

我搜索了很多次,但还是没找到可行的解决方案。如果我在 /etc/network/interfaces 中单独设置 IP,我可以使用 /48 中的任何地址,尽管尝试全面添加 /48 都没有成功。这是我的工作配置。

auto he-ipv6
iface he-ipv6 inet6 v4tunnel
    address 2xxx:xxx:xxx:0:0:0:0:1
    netmask 64
    endpoint xx.xx.xx.xx
    local xx.xx.xx.xx
    ttl 255
    gateway 2xxx:xxx:xxxx:xxxx::1

在尝试分配 /48 时,我尝试将其附加到接口

   post-up ip -6 addr add 2001:xx:xx::/48

这个问题建议使用 ipv6 非本地绑定选项,或者在本地接口上绑定,我试过这个例子,但我不确定是否使用net.ipv6.ip_nonlocal_bind选项。

/sbin/ip -6 addr add 2001:db8::ffff:1/64 dev lo

使用 wget --bind-address [dress within range] google.com 进行测试,我得到以下结果

--2017-02-04 15:07:26--  (try: 3)  http://ipv6.google.com/
Connecting to ipv6.google.com (ipv6.google.com)|2a00:1450:4001:814::200e|:80... failed: Cannot assign requested address.
Retrying.

不行。我是不是看错了?有人有什么建议吗?

答案1

首先您需要了解,您从 HE 收到的三个前缀并不完全相同。

已为您分配一个/64链接前缀。这是您在隧道接口上应使用的唯一前缀。

您还被分配了两个路由前缀 one/64和 one /48。您可以在此问题中阅读有关链接前缀和路由前缀之间差异的更多信息: IPv6:“路由前缀”和“链接前缀”之间的区别?

路由前缀/64可直接用作另一个连接的网络接口上的链接前缀。可以/48根据需要细分为其他路由前缀和链接前缀。

如果您需要单个主机上的大量地址,则应从路由前缀之一中分配本地前缀。我强烈建议不要/64为此目的使用比 更短的前缀。本地前缀可以长于/64

添加本地路由的命令可能如下例所示:

ip -6 route add to local 2001:db8:f918:b1e2:086a:cee6::/96 dev lo

您可以在以下问题中阅读有关使用本地路线的更多信息: 在 Debian 上向网络接口添加整个 IPv6 /64 块

正在侦听的应用程序::将接收本地路由前缀中任何 IP 的流量。如果您需要明确绑定到本地路由覆盖的单个 IP 地址,则应用程序必须设置套接字选项。

答案2

我想做同样的事情,并成功修改了 Squid 以实现这一目标。我使用了 Squid 3 的 Debian 软件包(版本 3.4.8-6+deb8u4)的源代码。只要您使用与使用 wget 执行此操作相同的网络配置,它就会起作用。您不需要将要使用的每个 IP 分配给您的网络接口。很抱歉没有提供适当的补丁,但这就是我所做的。

src/FwdState.ccgetOutgoingAddress() 函数的最开始,我添加了以下内容:

String ipv6;
ipv6 = request->header.getByName("IPV6-Bind");
if (ipv6 != "") {
  AclAddress l;
  struct sockaddr_in6 sa6;
  inet_pton(AF_INET6, ipv6.rawBuf(), &(sa6.sin6_addr));
  /* don't do conn->local = sa6 because of operator overloading */
  l.addr = sa6;
  conn->local = l.addr;
  ipv6.clean();
  conn->flags |= COMM_FREEBIND;
  return;
}
ipv6.clean();

#include <arpa/inet.h>我还在顶部添加了头文件src/FwdState.cc

然后,在 中src/comm.cc,我在创建套接字之后(即 之后new_socket = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol);)在 comm_openex() 中添加了以下代码块:

if ((flags & COMM_FREEBIND)) {
  int v = 1;
  if (setsockopt(new_socket, SOL_IP, IP_FREEBIND, (char *) &v, sizeof(v)) < 0) {
    debugs(50, DBG_IMPORTANT, "comm_openex: setsockopt() on FD " << new_socket << ": " << xstrerror());
  }
}

最后,在中src/comm/Connection.h我添加了以下内容:

#define COMM_FREEBIND           0x40

这些修改允许您通过向请求添加名为 IPV6-Bind 的 HTTP 标头来选择 IPv6 源地址。例如:IPV6-Bind: 2001:db8:f918:b1e2:086a:cee6::1

你可以用 wget 进行测试:

http_proxy='http://localhost:3128' wget -4 --header="IPV6-Bind: 2001:db8:f918:b1e2:086a:cee6::1" http://whatismyip.org/

注意:您应该能够使用 squid.conf 中的 request_header_access 指令来阻止将 IPV6-Bind 标头发送到网站。

相关内容