IPv6 – Proxy the neighbors (or come back ARP – we loved you really)
March 24, 2010
After three articles, where am I with my venture in to IPv6? What have we really achieved so far? Well, in functional terms, not so very much yet!!
To recap:
- Here I covered a lot of ground, getting basic IPv6 running on a Linux gateway box connected to an ISP providing native IPv6, while remembering stuff like the need to set up a firewall.
- Here I looked at the issue of IPv6 firewall logging
- And here I looked at the need to set up a default route out of the gateway device pointing back towards the internet.
And what can I now actually do? Well……. from the gateway box I can ping out successfully to any IPv6 device on the Internet. In other words, logged in to the device in green on this diagram, I can ping out of eth0 over the Internet. And from an IPv6 device on the Internet I can successfully ping towards my green box, using the address of eth0. So I can ping from the Internet to (these are of course made-up addresses!) 123::456.

However if from my remote Internet location I ping instead the IPv6 address of eth1 (here 123::789) does it work? I might expect it to: after all, eth1 has a global IPv6 address on it, not a private address. So surely I can ping it?
Needless to say, as it stands I cannot. Here we look at why not – in the process covering an important element of turning our gateway device in to an IPv6 router (which, grand though it sounds, is exactly what we are doing here!) which receives very little coverage elsewhere on the Internet. In fact when researching this I came to a conclusion that the vast majority of folks who have dabbled with IPv6 in the domestic environment have terminated their ISP IPv6 connection on their workstation, and very few have gone the step further and used a device as a gateway to a home network!!
How to get through the gateway – or Come back ARP, all is forgiven
So when I ping 123::789 what stops it working? The first thought is: firewall. We’re blocking it, right? A quick trip to the shorewall6 log (glad we set that up, eh?) shows us: nothing. Nowt. Zilch. Nada. Surprisingly, we’re not dropping the ping. (In fact the firewall config we set up in the first of these articles contains enough already to allow, from a firewall perspective, for this ping to succeed.)
So we now run tcpdump on eth0 to see just what is going on. Here’s an example:
From the remote host
From my remote IPv6 host I do and see:
ping6 2a01:e35:8b25:7ea0::22PING 2a01:e35:8b25:7ea0::22(2a01:e35:8b25:7ea0::22) 56 data bytesFrom 2a01:e35:8b25:7ea0::1 icmp_seq=1 Destination unreachable: Address unreachableFrom 2a01:e35:8b25:7ea0::1 icmp_seq=2 Destination unreachable: Address unreachableFrom 2a01:e35:8b25:7ea0::1 icmp_seq=3 Destination unreachable: Address unreachable...
Which doesn’t tell me a lot.
On the gateway
On my gateway, from tcpdump, I see:
tcpdump -i eth0 -v ip6tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes08:51:35.315038 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::207:cbff:fea5:1a68 > ff02::1:ff00:22: [icmp6 sum ok] ICMP6, neighbor solicitation, length 32, who has 2a01:e35:8b25:7ea0::22source link-address option (1), length 8 (1): 00:07:cb:a5:1a:6808:51:36.315002 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::207:cbff:fea5:1a68 > ff02::1:ff00:22: [icmp6 sum ok] ICMP6, neighbor solicitation, length 32, who has 2a01:e35:8b25:7ea0::22source link-address option (1), length 8 (1): 00:07:cb:a5:1a:6808:51:37.315001 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::207:cbff:fea5:1a68 > ff02::1:ff00:22: [icmp6 sum ok] ICMP6, neighbor solicitation, length 32, who has 2a01:e35:8b25:7ea0::22source link-address option (1), length 8 (1): 00:07:cb:a5:1a:68
What does this tell me?
So the ping is reaching the gateway device alright. Sort of. Well, not really. But there’s something going on there! What we see in that tcpdump trace is the ISP’s router to which I’m connected is sending me a Neighbor Solicitation for the ::22 address (i.e. the global IPv6 address of my eth1 interface on the “far side” of my gateway which I’m trying to ping) While I’m not keen to draw too many parallels and comparisons with IPv4, it is useful to do so here: A Neighbor Solicitation is, at least as we see it here, pretty much analogous to a good ol’ ARP Request. The ISP is saying to us “I think this address is somewhere over with you – Please confirm and let me know how to reach it”. Which is great, except for the glaring fact that we appear to ignore this NS (Neighbor Solicitation) and hence the ping fails.
So you can guess we need to set something up on the gateway that tells it to reply to such a NS. (Kinda vaguely analogous to a Proxy ARP, if you’re familiar with that)
IPv6 Proxy
A couple of steps here. Firstly the system needs to be told globally to perform the required IPv6 proxying, and we then need to enable it for specific addresses.
proxy_ndp
In the /etc/sysctl.conf file add a line:
net.ipv6.conf.all.proxy_ndp = 1
To set this dynamically (without a reboot) you can also do:
sysctl -w net.ipv6.conf.all.proxy_ndp=1
Neighbor proxy
Then perform:
ip -6 neigh add proxy 2a01:e35:8b25:7ea0::22 dev eth0
Note that here the IPv6 address is the address of the interface on the private side of the gateway (eth1 for me). The end part “…dev eth0″ is to say “Proxy that address from this interface”.
You also, of course, will need to make such configuration permanent. Numerous approaches to that: I settled upon adding this from the interface-up scripts in /etc/network/if-up.d/ but there are so many other methods too. Pick yours.
(Interestingly, I have yet to discover any way at all to display the list of proxied neighbors added in this manner! I’ve looked pretty hard, but there appears to be no way I can find to have them listed. There must be a way, but I can’t find it.)
Success!
And the ping now works, with a tcpdump like this now showing to us:
09:18:18.644817 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::207:cbff:fea5:1a68 > ff02::1:ff00:22: [icmp6 sum ok] ICMP6, neighbor solicitation, length 32, who has 2a01:e35:8b25:7ea0::22source link-address option (1), length 8 (1): 00:07:cb:a5:1a:6809:18:18.868550 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 32) fe80::240:63ff:fef5:f93c > fe80::207:cbff:fea5:1a68: [icmp6 sum ok] ICMP6, neighbor advertisement, length 32, tgt is 2a01:e35:8b25:7ea0::22, Flags [solicited]destination link-address option (2), length 8 (1): 00:40:63:f5:f9:3c09:18:18.868958 IP6 (hlim 56, next-header ICMPv6 (58) payload length: 64) ipsi6 > 2a01:e35:8b25:7ea0::22: ICMP6, echo request, length 64, seq 509:18:18.869107 IP6 (hlim 64, next-header ICMPv6 (58) payload length: 64) 2a01:e35:8b25:7ea0::22 > ipsi6: ICMP6, echo reply, length 64, seq 5
Which has 4 elements:
- The same sort of Neighbor Solicitation we had previously.
- This time we send back a Neighbor Advertisement for the ::22 address
- With that done, the ping itself can come to us (the ICMP6 echo request)
- And we of course respond to the ping with ICMP6 echo reply.
Conclusions and summary
In the world of IPv6, with no ARP or NAT, life is different. Devices which in IPv4 are thought of as private (both in terms of addressing and functionality) are now, at least from the perspective of addressing, public. We need to make sure that if we want “The World” to be able to reach them, we must in turn tell the world about them. Hence the need for IPv6 neighbor proxying. And, thinking ahead a little, the need to take our firewalling ever more seriously. If I make the addresses of a “private” workstation globally reachable I’d better make sure that it’s protected…
The last point to make is about scalability: do we really need to add an “ip -6 neigh add proxy” for each private device we wish to be able to reach from the Internet? If there are only a few devices (as in the typical home network) then it may well be easiest to do this. However in situations where the private side of the network has many IPv6 addresses which need to be globally reachable, other solutions may be more appropriate and manageable, but will not be covered here. Here we’re trying to get a small home network IPv6 enabled, not migrate a corporation to IPv6. If you really want to get in to the area of automating these functions you need to read up on implementations of Neighbor Discovery Protocol, look at “zeroconfig” networking, Apple’s Bonjour service, and so on..
There will come a time when such automation will be required at the domestic level, with the eventual proliferation of networked devices. But for now we keep it simple and statically configure the required addresses.
4 Responses to “IPv6 – Proxy the neighbors (or come back ARP – we loved you really)”
Hello,
Good post, very userful. I’ve been struggling with ipv6 routing for some time, and the problem was that my router wasn’t answering the ICMPv6 Neighbour Solicitation messages.
I made it work on a per host basis, with “ip -t neigh add …”, e.g.:
ip -6 neigh add proxy 2001:xxxx:2:yyyy:a000::2 dev eth0
But how can it be done to proxy for a subnet?
Scenario:
Router with a /64 native ipv6 network assigned.
Behind the router, 2 different networks, each a /68
How could I make the router answer neighbor solicitations for each /68 subnet, so that the packets can reach the router and can be forwarded to the specific subnet?
Thanks!
By Julian J. M. on Apr 11, 2010
Good question! In a couple of words: “I don’t know. Yet”
When writing up my mini IPv6 howtos one of the things that has genuinely surprised me is the relative immaturity of IPv6 implementation for a small home device, when taken a a whole. Most of the elements themselves are robust and have actually been around for years now. But hanging them all together is clearly something that not too many people have yet done!
I do not yet know of a Linux service which will allow me to respond to Neighbor Solicitations for a range of addresses. Sure, with RAD I can myself act as a router and advertise networks, as I do to my internal network. But the specific function of sending a neighbor advertisement based upon a range of addresses? I currently simply do not know. I guess what you (and I) are really looking for is a command along the lines of:
ip -6 neigh add proxy 1111:2222:3333:4444/64
so that any neighbor solicitation received for an address within the subnet gets responded to?
I’ll keep looking – I find it hard to believe it’s not possible. But I do not know how today.
By sgroarke on Apr 13, 2010
Adding a bit to my comment above about Neighbor Discovery: maybe a quick ‘n dirty NAD (Neighbor Advertisement Daemon) needs writing!
RFC 3756 details the security considerations of an implementation of NDP. Of the three models described therein, we would want to consider ourselves as a “Corporate Internet”, as we trust ourself and the private-side devices attached to us. And, anyway, in the home environment we will only typically have a single router: our gateway device itself. So I think that this model is correct.
The IETF’s Secure Neighbor Discovery will likely form the basis of NDP in the longer term. But in the shorter term it would seem that we could perform NDP as per RFC 4861 and fill a bit of a hole that exists today.
The hole is that IPv6 implementations to date seems to assume that a device is either a full-fledged router or it is an end-point. While “our” gateway device can and does act as a full-fledged router (I can kick out via RADVD router advertisements to my heart’s content) my ISP sees me as an end-point. It sends me router advertisements, but isn’t interested in seeing any back (which, from a security model point of view, is not wholly unreasonable!) When it wants to “route” anything within the /64 range to me it first requires a satisfactory neighbor solicitation/advertisement exchange to take place.
Hence the need to proxy the IPv6 neighbour discovery.
Watch this space. I might just rustle something up…! In the near future I might be after a beta tester or two.
By sgroarke on Apr 13, 2010