First, thank you! The "ndp -s" trick does exactly what I need. (I did
not need to consider ndp-reflector.) The rest of this email could be
summarized as "That works so perfectly I would pay for someone to make
it automatic; meanwhile the other things I asked about were in fact
bad ideas and I will stop wishing for them."

> What you're actually trying to do here is respond to NDP requests as a
> proxy. It's not a clean way to do it (the clean way is "upstream routes
> you a subnet"), but some people are trying to do this on cheap services
> that are only intended for a single host connection and that's about the
> only way.
>
> In this case you might be able to do it with ndp -s, as the "proxied"
> address is down a tunnel and not going to respond to NDP itself anyway,
> so it doesn't hit the main problem for arp/ndp proxy in OpenBSD which
> is that it answers on all interfaces, you can't tie it to one in
> particular.
>
> (For some other use cases, where you're on a /64 behind an ISP router,
> and have other hosts on a different ethernet interface, it looks like
> https://github.com/toru-mano/nd-reflector might do the trick).

What makes it unclean? (The "ndp -s" trick is simple and works
perfectly; I'm trying to understand why it's architecturally bad.) The
use case is:
- I have a whole /64 subnet.
- I cannot easily modify the gateway router on this subnet.
- I want to connect a single client to this network over a tunnel that
  is administered by a host (not the gateway router!) on that network.
- I want the client to be assigned a single [dynamic] IPv6 address on
  the /64 subnet. This address must be globally routable!
- IPv4 is explicitly out-of-scope because addresses are hard to come
  by; I'm fine just using NAT for IPv4.

These items describe both my VPS (where the hypervisor has allocated me
an entire /64 subnet but only delivers packets to the vio0 interface
when their destination addresses can be found among my NDP neighbor
advertisements) and my physical network at home (where again the whole
/64 is mine, but replacing the ISP-provided router is a nontrivial
affair).

Since iked already supports dynamic address assignments, that part is
noncontroversial. What is needed for this address to be globally
routable? The Internet at large already knows how to look at the top
64 bits of an address to figure out what gateway router to deliver the
packet to, and if the packet somehow reaches the IKEv2 responder, iked
has already set up the routes necessary to push the packet down the
tunnel to its final destination. All we're missing is the step between
the gateway router and the IKEv2 responder. They're on the same link.
What is the proper way to for iked to announce the dynamic IPv6 address
to other hosts on the local link? NDP. And it turns out that OpenBSD
already has a utility in base that does NDP proxying. It seems like
this should be the recommended solution for IPv6. Taking responsibility
for routing the whole /64 subnet just to support a couple of IPsec
tunnels seems wrong. I'm not trying to bridge networks; I just want to
use an IPsec tunnel to proxy traffic from my laptop. The "ndp -s"
trick seems simple and elegant, and it does exactly what we need it to
and no more.

I would go a step further and ask if *this* functionality could be done
automatically by iked. I looked at the code in the ndp utility and it
appears to work just by writing messages to a kernel routing socket.
Seeing as iked *already* writes messages to a routing socket whenever a
flow starts or stops, it seems like it would be easy (and
architecturally sound) to add an option to tell iked to do the
equivalent of calling "ndp -s $client_addr $server_mac proxy" when a
client connects and "ndp -d $client_addr" when it disconnects---just
treat it like any other routing step. It could be enabled with a
configuration option like "ndp-proxy vio0". (The point of the interface
name is to free me from the burden of entering the MAC address by
hand.) The option would only be valid for connections with a "config
address" option where the address is an IPv6 address, because of course
that is the address which would be added to the NDP proxy list.

I would gladly pay $200 to a developer who can add this functionality
to iked. That's one reason I care so much about whether this is really
a "clean" solution. If it isn't clean then maybe adding it isn't such a
good idea. But to *me* it looks like iked is already responsible for
updating routing information to match the currently-active flows, and
the code in the ndp utility suggests that from the kernel's point of
view, neighbor advertisements are a routing issue controlled through a
routing socket. I can automate this process with a script, but I really
do think this is the right way to do "road warrior" IPv6 connections.


>> So what would be fantastic is if instead of
>> putting "config address 2001:db8:2::/64" in the responder's iked.conf,
>> I could put "config inet6 autoconf vio0" instead. Then iked would
>> make sure that vio0 is using autoconf addresses and, if so, it would
>> request a new address via SLAAC (preferably randomizing all 64 bits
>> instead of just the bottom 32 bits like it does right now), assign
>> that address to the client, configure all the routing, and then would
>> somehow configure vio0 to claim ownership of that address for
>> NDP neighbor solicitation purposes, but have the kernel *not* claim
>> the address for routing purposes. The client config wouldn't change
>> at all; it would still say "request address any".
>
> autoconf privacy addresses require that old addresses stay active so
> that long-running connections don't die. You're asking hell of a lot
> from a number of different subsystems, some of which do not have a way
> to handle this, to make it all work.

That's a fair point. I assumed this could be handled entirely on the
client side, by having the client periodically open up new flows. but
apparently IKEv2 has a state machine concept that might not be so
friendly to dynamically varying the number of active routes between the
initiator and the responder. So, never mind.

I also see more complexity with the "autoconf eth0" idea (even after
dropping the idea of temporary addresses)---if there are multiple IPv6
routers blurting advertisements on eth0's link, then there's no good
way for iked to choose which of the addresses to assign to the tunnel.
If the goal is for the client to join *all* of the available networks
which happen to be on the Ethernet link, then this is logically a layer
2 tunnel ("show me all the Ethernet traffic") and not a layer 3 tunnel
("show me everything with this IP address"), so it doesn't make sense
to bundle that with IP-level routing rules. So never mind to this, too.

That said, I repeat my offer of $200 if you (or someone else with
OpenBSD commit rights) can automate the process of enabling and
disabling NDP proxying for responder-assigned IPv6 addresses. I am
firmly convinced that this is a good idea because my VPN setup was
unusable until I tried "ndp -s".


> -- 
> Please keep replies on the mailing list.

Oops, Tobias' reply included me on the To: line so I assumed I was
supposed to do the same. This reply is to the misc list only.

Thanks,
Anthony Coulter

Reply via email to