0

I have an Ubuntu 14.05 server running Squid. It has an IPv6 connection via Hurricane Electric's service. I'm trying to have every IP available to the server from the /48 they offer.

I've searched signifcantly and haven't found a working solution. I can use any address from the /48 if I set the IPs individually within /etc/network/interfaces, though attempts at blanket adding the /48 haven't worked. Heres my working conf.

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

In attempts to assign the /48 I've tried appending this to interfaces

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

This question suggests using ipv6 non local bind option, or binding on the local interface, I tried this example, though I'm not certain on using the net.ipv6.ip_nonlocal_bind option.

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

Testing using wget --bind-address [dress within range] google.com I get the following

--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.

No dice. Am I looking at this in the wrong way? Does anyone have a suggestion?

jblz
  • 195
  • 1
  • 2
  • 10
  • Trying to use a network size other than `/64` breaks some things in IPv6. Are you wanting the single host to use a `/48` network? Typically, you would use a `/64` for the transit network (HE gives you that, too), and you would then delegate the `/64` prefixes of the `/48` prefix in your router. Each individual network would be assigned a `/64` prefix through IPv6 Prefix Delegation. – Ron Maupin Feb 04 '17 at 16:02
  • 2
    Why are you trying to do this? – Michael Hampton Feb 04 '17 at 19:45
  • @Ron in that case would my only option to use something like pfSense? – jblz Feb 05 '17 at 02:26
  • @MichaelHampton I'm working my through the HE certs and became curious. I'd like to give Squid the ability to use any address from the /48 – jblz Feb 05 '17 at 02:28

2 Answers2

3

First of all you need to understand that the three prefixes you have received from HE are not all the same.

You have been allocated one /64 link prefix. This is the only prefix you should be using on the tunnel interface.

You have also been allocated two routed prefixes one /64 and one /48. You can read more about the difference between link prefixes and routed prefixes in this question: IPv6: differences between "routed prefix" and "link prefix"?

The routed /64 can be used directly as a link prefix on another attached network interface. The /48 can be subdivided into other routed and link prefixes as needed.

If you need a lot of addresses on a single host you should allocate a local prefix out of one of your routed prefixes. I strongly advice against using a prefix shorter than /64 for that purpose. The local prefix can be longer than /64.

The command to add a local route could look like this example:

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

You can read more about using local routes in this question: Adding a whole IPv6 /64 block to an network interface on debian

Applications listening on :: will receive traffic for any IP in the prefix of your local route. If you need to explicitly bind to individual IP addresses covered by a local route, the application has to set a socket option.

kasperd
  • 29,894
  • 16
  • 72
  • 122
  • There is a lot very informative, well written info in your response(s). Largely through your posts have I understood this and got it working (in theory). I recompiled wget to use IP_FREEBIND - this works great, but did not have as much luck adding the setsockopt in the Squid3 source (I think I added the option into the correct place in src/conn.cc but when I recompile with the /configure options for Ubuntu in the Squid3 documentation gives me there doesn't appear to a proper installation of Squid. Though this is perhaps a question in its own right). Thank you. – jblz Feb 20 '17 at 21:19
  • Can you please explain why you've strongly advised against a local prefix no shorter than /64? – jblz Feb 20 '17 at 21:20
  • 1
    @jblz I can't imagine any scenario where you would need more than 18446744073709551616 local IPv6 addresses on a single host. If you were to use your entire routed prefix in a local route you wouldn't have any addresses left when you need another link or routed prefix on your LAN. – kasperd Feb 20 '17 at 22:26
0

I wanted to do the same thing and successfully modified Squid to achieve that. I used the source code of the Debian package of Squid 3 (version 3.4.8-6+deb8u4). It will work provided you use the same network configuration you used for doing this with wget. You won't need to assign every IP you want to use to your network interface. Sorry for not providing proper patches, but here's what I did.

In src/FwdState.cc, at the very beggining of the getOutgoingAddress() function, I added this:

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();

I also added the header file #include <arpa/inet.h> at the top of src/FwdState.cc.

Then, in src/comm.cc, I added this block of code in comm_openex(), right after the creation of the socket (i.e. after new_socket = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol);):

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());
  }
}

Finally, in src/comm/Connection.h, I added this:

#define COMM_FREEBIND           0x40

These modifications allow you to choose your IPv6 source address by adding an HTTP header named IPV6-Bind to the request. For example: IPV6-Bind: 2001:db8:f918:b1e2:086a:cee6::1.

You can test with wget:

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

Note: you should be able to prevent the IPV6-Bind header to be sent to the website by using the request_header_access directive in your squid.conf.

Geoffroy
  • 1
  • 1
  • Does `IPV6-Bind` absolutely have to use incorrect capitalization? – kasperd Apr 10 '17 at 21:04
  • 1
    @kasperd No, the correct capitalization should definitely be used. The "Referer" HTTP header is enough, we don't need more terrible mistakes. Fortunately, serverfault is a collaborative website. I provide an answer to the question, and you provide the correct capitalization of IPV6. – Geoffroy Apr 10 '17 at 22:34