Bug 2512 - Use IP_FREEBIND if available for sshd listening socket
Summary: Use IP_FREEBIND if available for sshd listening socket
Status: NEW
Alias: None
Product: Portable OpenSSH
Classification: Unclassified
Component: sshd (show other bugs)
Version: 7.1p1
Hardware: Other Linux
: P5 enhancement
Assignee: Assigned to nobody
URL:
Keywords: patch
Depends on:
Blocks:
 
Reported: 2015-12-09 01:04 EST by Jakub Jelen
Modified: 2016-01-07 00:37 EST (History)
1 user (show)

See Also:


Attachments
proposed patch (635 bytes, patch)
2015-12-09 01:04 EST, Jakub Jelen
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jakub Jelen 2015-12-09 01:04:36 EST
Created attachment 2763 [details]
proposed patch

I had the feeling that this issue was discussed here or on mailing list, but I can't find it anywhere, so opening new bug.

# Background
Systemd starts sshd server quite early during boot sequence, which means in some setups, address of network interface might not be available yet. This causes sshd to fail (if there is only one default ListenAddress option) and start is tired again later, when the address is ready to use.

# Problem
When there is defined multiple ListenAddress (local and non-local or yet non-existent) in sshd_config, the initial startup does fail only on non-local address, but the overall start is successful. This results in sshd listening only on localhost address which is usually not much useful.

# Solution
This can be solved by setting listening socket option IP_FREEBIND, which allows bind to even non-existing or non-local addresses and as described in [1]. This feature is available in Linux since 2.4

There is still available workaround with system-wide boolean /proc/sys/net/ipv4/ip_nonlocal_bind, but having this set up fine grained per-socket seems like more reasonable.

# Downside
Only downside I can think of is that users will not see the configuration errors, if they mistype IP address in configuration file. This can be solved by allowing this only based on some other option or environment variable (not part of attached patch). Patch was tested on RHEL 7.0.

[1] http://linux.die.net/man/7/ip
Comment 1 Damien Miller 2015-12-14 11:14:04 EST
Why can't systemd start sshd after the interfaces have been brought up?
Comment 2 Jakub Jelen 2015-12-15 02:28:03 EST
The thing is that systemd provides network-online.target [1] and network.target [2], but the specification what does it mean is quite vague and it does not tell (for example) which network interface is ready on systems with more network interfaces.

So far you can take this more like an idea to discuss and track, than intention to apply the patch in this form. We are still investigating this behaviour and currently I incline more to have this as config option or environment variable, rather than turning it on everywhere.

[1] http://www.freedesktop.org/software/systemd/man/systemd.special.html#network-online.target
[2] http://www.freedesktop.org/software/systemd/man/systemd.special.html#network.target
[3] http://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/
Comment 3 Jakub Jelen 2015-12-23 20:58:23 EST
(In reply to Damien Miller from comment #1)
> Why can't systemd start sshd after the interfaces have been brought
> up?

It is the default behaviour to depend on network.target, which waits before interface is up. But bringing device up is not bringing device online and setting the correct IP, especially when there is DHCP (if I understand it well). This works fine on fast DHCP or static setups.

You can set the dependency on network-online.target, but it brings other dependencies in the boot sequence and slows down the boot.

Having the possibility to use IP_FREEBIND as a configuration option (ListenAddressFreeBind or some prefix (-) in front of address itself?) would give us fast boot itself and possibility to tune the network addresses behaviour if needed.
Comment 4 Damien Miller 2015-12-24 09:07:46 EST
(In reply to Jakub Jelen from comment #3)

> You can set the dependency on network-online.target, but it brings
> other dependencies in the boot sequence and slows down the boot.

Doesn't this only affect users who change ListenAddress from the wildcard default? If so, can't they simply choose between wildcard+early or bound+depends-on-network-online?
Comment 5 Jakub Jelen 2016-01-07 00:37:07 EST
(In reply to Damien Miller from comment #4)
> (In reply to Jakub Jelen from comment #3)
> 
> > You can set the dependency on network-online.target, but it brings
> > other dependencies in the boot sequence and slows down the boot.
> 
> Doesn't this only affect users who change ListenAddress from the
> wildcard default? If so, can't they simply choose between
> wildcard+early or bound+depends-on-network-online?

Yes, you are right. Default wildcard works fine.

On machines with more network interfaces you are more liable to start fiddling with ListenAddress.
Using IP_FREEBIND sounds like a reasonable alternative to the second one.