Discussion:
krb5 UDP daemons and IP pktinfo
Greg Hudson
2016-01-05 21:58:35 UTC
Permalink
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 ***@mit.edu
https://mailman.mit.edu/mailman/listinfo/krbdev
Simo Sorce
2016-01-05 22:22:10 UTC
Permalink
Post by 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
* 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 ***@mit.edu
https://mailman.mit.edu/mailman/listinfo/krbdev
Benjamin Kaduk
2016-01-06 04:56:29 UTC
Permalink
Post by Greg Hudson
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 ***@mit.edu
https://mailman.mit.edu/mailman/listinfo/krbdev
Kenneth G Raeburn
2016-01-12 06:58:41 UTC
Permalink
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.
Post by Greg Hudson
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 ***@mit.edu
https://mailman.mit.
Greg Hudson
2016-01-12 07:28:51 UTC
Permalink
Post by Kenneth G Raeburn
Post by Greg Hudson
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 ***@mit.edu
https://mailman.mit.edu/mai

Loading...