3

I have multiple network interfaces like Ethernet, Wifi, WWAN etc.

I want to block SSH root login on all interfaces except for the Ethernet one.

Is there an interface-based configuration for sshd, like some setting in /etc/ssh/sshd_config?

I could not find interface-based settings in the settings manual: https://man.openbsd.org/sshd_config

On my WWAN interface, I get attacks from intruders like these, which I want to avoid:

systemd[1]: Condition check resulted in OpenSSH Key Generation being skipped.
systemd[1]: Started OpenSSH Per-Connection Daemon (195.133.18.24:45650).
sshd[704]: Invalid user user from 195.133.18.24 port 45650
sshd[704]: error: Could not get shadow information for NOUSER
sshd[704]: Failed password for invalid user user from 195.133.18.24 port 45650 ssh2
sshd[704]: Received disconnect from 195.133.18.24 port 45650:11: Normal Shutdown, Thank you for playing [preauth]
sshd[704]: Disconnected from invalid user user 195.133.18.24 port 45650 [preauth]
systemd[1]: [email protected]:22-195.133.18.24:45650.service: Succeeded.

3 Answers 3

4

Is there a possible 'interface' based configuration for SSH daemon, like some setting in /etc/ssh/sshd_config?

Yes, in /etc/ssh/sshd_config you can specify the interface(s) on which your sshd service will listen to. The setting is called "ListenAddress".

If ListenAddress setting is not in the config, then the default is to listen on all local addresses.

Unfortunately, that setting can't take an interface name, but it can take the interface IP address (and port) -- which solves your problem. Example:

echo "ListenAddress 192.168.55.101:40022" >>/etc/ssh/sshd_config
/etc/rc.d/rc.sshd restart
2
  • ListenAddress (and Port) directives are cumulative, so in many cases, it may be better to edit sshd_config and search for any pre-existing directives, rather than unconditionally adding one to the pile.
    – Jim L.
    Commented Nov 29, 2021 at 7:05
  • @JimL. : Yes, editing the config is the proper thing to do. I just gave him a quick hack to point him in the right direction.
    – Pourko
    Commented Nov 29, 2021 at 7:58
3

Use a firewall rule – for example, nftables or iptables. (Firewalld may also be able to do this with "zones".) This is the most versatile option; both nftables and iptables support wildcards, and both actually prevent connections from the incorrect interface (which is not relevant against internet bots, but can be relevant when guarding against malicious local users on wlan0).

  • For example, in nftables you would write:

    table inet filter {
        chain input {
            [...]
            tcp dport 22 iifname "eth*" accept
            tcp dport 22 reject
            [...]
        }
    }
    
  • In iptables .rules files, the same is:

    [...]
    -A INPUT -p tcp --dport 22 -i eth+ -j ACCEPT
    -A INPUT -p tcp --dport 22 -j REJECT
    [...]
    

Your system uses per-connection sshd instances ("inetd style" or "socket activated") rather than the usual standalone daemon. In this mode, the listen addresses are not decided by the sshd but by the supervisor (super-server).

With systemd socket activation, run systemctl edit --full sshd.socket to define the listen addresses, replacing the existing ListenStream= options with:

[Socket]
ListenStream=192.168.55.101:22

Alternatively, you can keep the global ListenStream=, but bind the socket to only a specific interface (exact name only, wildcards not allowed):

[Socket]
ListenStream=0.0.0.0:22
ListenStream=[::]:22
BindToDevice=eth0

Afterwards, restart sshd.socket to apply the changes.

Note that this inetd-mode is generally not recommended for sshd, as the bruteforce bots may cause systemd's rate-limiting to kick in and prevent you from making even legitimate connections. You should consider disabling sshd.socket and enabling the "standalone" sshd.service instead. (After doing so, the listen addresses will be controlled by /etc/ssh/sshd_config instead.)

1

Adding to u1686_grawity answer... Now in Ubuntu 24.04 LTS, it appears sshd-socket-generator checks in the sshd configuration (sshd_config and /etc/ssh/sshd_config.d/ ) for Port and listenaddress directives, then transposes these directives into /run/systemd/generator/ssh.socket.d/addresses.conf as ListenStream directives.

For example if Port 22 was specified in sshd_config, then addresses.conf will receive:

[Socket]
ListenStream=
ListenStream=22

or if sshd_config also contains listenaddress 192.168.1.10, then addresses.conf becomes:

[Socket]
ListenStream=
ListenStream=192.168.1.10:22
  • It works also with ipv6.
  • Important: the first empty line ListenStream= erases previous ListenStream directives from /etc/systemd/system/ssh.socket, and only keeps the ones from sshd-socket-generator.

Conclusion:

  • run systemctl edit --full ssh.socket,
  • specify the BindToDevice=eth0 directive,
  • don't specify any ListenStream (they won't be taken into account),
  • then run sudo systemctl daemon-reload && sudo systemctl restart ssh.socket,
  • this lets sshd-socket-generator copy the Ports and listenaddress directives from the sshd configuration.

Review your configuration with:

  • systemctl cat ssh.socket
  • ss -tuln
  • sshd -T

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .