krb5 UDP daemons and IP pktinfo

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

krb5 UDP daemons and IP pktinfo

Greg Hudson
MIT krb5 contains two UDP daemons, krb5kdc and kadmind (for password
changes).  For UDP daemons, it is sometimes important to send replies
from the same address as the requests were sent to, or the replies may
be discarded by firewalls or NAT devices.  The BSD sockets interface
does not provide this functionality if you bind the server socket to the
wildcard address.  For IPv6, there is a standardized and widely
implemented extension (IPV6_PKTINFO) which provides the needed
functionality.  For IPv4, the situation is more fragmented (see below).
As a result, we have some complicated code in lib/apputils/net-server.c
which does the following for each of IPv4 and IPv6:

* If pktinfo suport is present, we bind to the wildcard address and set
  the socket to use pktinfo.

* Otherwise, we loop over the local interfaces and bind to each one.  We
  also bind to the routing socket.  When a message is received on the
  routing socket indicating that local interfaces have changed, we close
  all sockets (including active TCP connections) and rebind listener
  sockets from scratch.

In 2010 I asked for help doing a platform survey, and found that while
Linux and Solaris 11 implement an IPv4 variant of pktinfo (IP_PKTINFO),
other platforms do not (NetBSD added it in 2013).  Until yesterday, my
operating assumption was that we were stuck with the complex code for
the forseeable future.  Yesterday, I discovered that some operating
systems implement the same functionality in a different way
(IP_RECVDSTADDR).  If we handle both variants, then we can safely bind
to the IPv4 wildcard address on Linux, Solaris, all of the BSDs, and OS
X.

So, I think it might be reasonable to simplify the net-server.c code at
the expense of some degradation on the rare platforms which don't
implement either variant of IPv4 pktinfo.  My favored form of
degradation is that we always bind to the wildcard address, and if the
platform doesn't have IPv4 pktinfo support, we just let sendto() pick
the source address of the reply.  For those platforms, our UDP daemons
will continue to work on single-homed machines, but might not behave
properly on multi-homed machine depending on the routing configuration.

Do other people agree that this is reasonable?
_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev
Reply | Threaded
Open this post in threaded view
|

Re: krb5 UDP daemons and IP pktinfo

Simo Sorce-3
On Tue, 2016-01-05 at 16:58 -0500, Greg Hudson wrote:

> MIT krb5 contains two UDP daemons, krb5kdc and kadmind (for password
> changes).  For UDP daemons, it is sometimes important to send replies
> from the same address as the requests were sent to, or the replies may
> be discarded by firewalls or NAT devices.  The BSD sockets interface
> does not provide this functionality if you bind the server socket to the
> wildcard address.  For IPv6, there is a standardized and widely
> implemented extension (IPV6_PKTINFO) which provides the needed
> functionality.  For IPv4, the situation is more fragmented (see below).
> As a result, we have some complicated code in lib/apputils/net-server.c
> which does the following for each of IPv4 and IPv6:
>
> * If pktinfo suport is present, we bind to the wildcard address and set
>   the socket to use pktinfo.
>
> * Otherwise, we loop over the local interfaces and bind to each one.  We
>   also bind to the routing socket.  When a message is received on the
>   routing socket indicating that local interfaces have changed, we close
>   all sockets (including active TCP connections) and rebind listener
>   sockets from scratch.
>
> In 2010 I asked for help doing a platform survey, and found that while
> Linux and Solaris 11 implement an IPv4 variant of pktinfo (IP_PKTINFO),
> other platforms do not (NetBSD added it in 2013).  Until yesterday, my
> operating assumption was that we were stuck with the complex code for
> the forseeable future.  Yesterday, I discovered that some operating
> systems implement the same functionality in a different way
> (IP_RECVDSTADDR).  If we handle both variants, then we can safely bind
> to the IPv4 wildcard address on Linux, Solaris, all of the BSDs, and OS
> X.
>
> So, I think it might be reasonable to simplify the net-server.c code at
> the expense of some degradation on the rare platforms which don't
> implement either variant of IPv4 pktinfo.  My favored form of
> degradation is that we always bind to the wildcard address, and if the
> platform doesn't have IPv4 pktinfo support, we just let sendto() pick
> the source address of the reply.  For those platforms, our UDP daemons
> will continue to work on single-homed machines, but might not behave
> properly on multi-homed machine depending on the routing configuration.
>
> Do other people agree that this is reasonable?

Sounds perfectly reasonable to me.

Simo.

--
Simo Sorce * Red Hat, Inc * New York

_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev
Reply | Threaded
Open this post in threaded view
|

Re: krb5 UDP daemons and IP pktinfo

Benjamin Kaduk-2
In reply to this post by Greg Hudson
On Tue, 5 Jan 2016, Greg Hudson wrote:

> Do other people agree that this is reasonable?

Yes, but maybe ask on kerberos@ if anyone has a multi-homed KDC on a
"weird" OS as a heads-up.

-Ben
_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev
Reply | Threaded
Open this post in threaded view
|

Re: krb5 UDP daemons and IP pktinfo

Kenneth G Raeburn
In reply to this post by Greg Hudson
> In 2010 I asked for help doing a platform survey, and found that while
> Linux and Solaris 11 implement an IPv4 variant of pktinfo (IP_PKTINFO),
> other platforms do not (NetBSD added it in 2013).  Until yesterday, my
> operating assumption was that we were stuck with the complex code for
> the forseeable future.  Yesterday, I discovered that some operating
> systems implement the same functionality in a different way
> (IP_RECVDSTADDR).  If we handle both variants, then we can safely bind
> to the IPv4 wildcard address on Linux, Solaris, all of the BSDs, and OS
> X.

Have you checked that it actually works?  It’s been a long time, but I remember running across IP_RECVDSTADDR, and I seem to recall that some options in this space didn’t seem to work as documented (or at all?) on some platforms, but I can’t recall for sure if IP_RECVDSTADDR was what was broken, and of course it could’ve been fixed since for the platforms you care about.

> So, I think it might be reasonable to simplify the net-server.c code at
> the expense of some degradation on the rare platforms which don't
> implement either variant of IPv4 pktinfo.  My favored form of
> degradation is that we always bind to the wildcard address, and if the
> platform doesn't have IPv4 pktinfo support, we just let sendto() pick
> the source address of the reply.  For those platforms, our UDP daemons
> will continue to work on single-homed machines, but might not behave
> properly on multi-homed machine depending on the routing configuration.
>
> Do other people agree that this is reasonable?

If RECVDSTADDR works and covers the important platforms that PKTINFO doesn’t, it sounds like quite a nice simplification.  That bit with the routing socket is pretty annoying.

Ken

_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev
Reply | Threaded
Open this post in threaded view
|

Re: krb5 UDP daemons and IP pktinfo

Greg Hudson
On 01/12/2016 01:58 AM, Kenneth G Raeburn wrote:
>> Yesterday, I discovered that some operating
>> systems implement the same functionality in a different way
>> (IP_RECVDSTADDR).  If we handle both variants, then we can safely bind
>> to the IPv4 wildcard address on Linux, Solaris, all of the BSDs, and OS
>> X.
>
> Have you checked that it actually works?  It’s been a long time, but I remember running across IP_RECVDSTADDR, and I seem to recall that some options in this space didn’t seem to work as documented (or at all?) on some platforms, but I can’t recall for sure if IP_RECVDSTADDR was what was broken, and of course it could’ve been fixed since for the platforms you care about.

It works on current FreeBSD in a test program[1].  It appears to be used
by FreeRADIUS[2] and PowerDNS[3].

OpenBSD currently appears to define IP_RECVDSTADDR but not
IP_SENDSRCADDR.  I don't know if the former can be used as the latter
(they have the same value in FreeBSD).

I also discovered that OS X has IP_PKTINFO in 10.9.  Windows also
appears to support it as of XP and Server 2003, although that's not
immediately important since we don't build the KDC or kadmind on Windows.

[1] I tested successfully on FreeBSD 10.2 in a VM.  Ben Kaduk ran my
test program on his FreeBSD machine and it gets EINVAL trying to send
from loopback to the host address.  We're not sure why, and we're not
sure whether it would be a concern for just mirroring the destination
address of a request to the source address of a reply.

[2]
https://github.com/FreeRADIUS/freeradius-server/blob/v3.1.x/src/lib/udpfromto.c

[3]
http://blog.powerdns.com/2012/10/08/on-binding-datagram-udp-sockets-to-the-any-addresses/
_______________________________________________
krbdev mailing list             [hidden email]
https://mailman.mit.edu/mailman/listinfo/krbdev