How to check that a daemon is listening on what interface?

(you might have to install the package ip on openwrt (v12 / attitude adjustment)

ifconfig/netstat etc. are considered deprecated, so you should use (as root)

ss -nlput | grep sshd

to show the TCP/UDP sockets on which a running program which contains the string sshd is listening to

  • -n
    no port to name resolution
  • -l
    only listening sockets
  • -p
    show processes listening
  • -u
    show udp sockets
  • -t
    show tcp sockets

Then you geht a list like this one:

tcp    LISTEN     0      128                    *:22                    *:*      users:(("sshd",3907,4))
tcp    LISTEN     0      128                   :::22                   :::*      users:(("sshd",3907,3))
tcp    LISTEN     0      128            127.0.0.1:6010                  *:*      users:(("sshd",4818,9))
tcp    LISTEN     0      128                  ::1:6010                 :::*      users:(("sshd",4818,8))

the interesting thing is the 5th column which shows a combination of IP address and port:

  1. *:22
    listen on port 22 on every available IPv4 address
  2. :::22
    listen on port 22 on every available IP address (i do not write IPv6, as IP is IPv6 per RFC 6540)
  3. 127.0.0.1:6010
    listen on IPv4 address 127.0.0.1 (localhost/loopback) and port 6010
  4. ::1:6010
    listen on IP address ::1 (0:0:0:0:0:0:0:1 in full notation, also localhost/loopback) and port 6010

You then want to know which interfaces has an IPv4 address (to cover 1.)

ip -4 a
# or "ip -4 address"
# or "ip -4 address show"

or an IP address (to cover 2.)

ip -6 a
# or "ip -6 address
# or "ip -6 address show

(if you do not add the option for IP (-6) or IPv4 (-4) both are shown)

You can also have an look that output and search for e.g. 127.0.0.1 or any other IP/IPv4-address

# here a demo where i show all addresses of the device "lo" (loopback)
ip a show dev lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever

The lines beginning with inet and inet6 show that these IPs are bound to this interface, you may have many of these lines per interface:

he-ipv6: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1480 qdisc noqueue state UNKNOWN
    link/sit 192.0.2.1 peer 192.0.2.3
    inet6 2001:db8:12::1/64 scope global
       valid_lft forever preferred_lft forever
    inet6 2001:db8::2/64 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::1111:1111/128 scope link
       valid_lft forever preferred_lft forever

and in a script:

address="127.0.0.1"
for i in $(grep ':' /proc/net/dev | cut -d ':' -f 1 | tr -d ' ') ; do
        if $(ip address show dev $i | grep -q "${address}") ; then
                echo "${address} found on interface ${i}"
        fi
done

(replace "127.0.0.1")


Using lsof (as root):

# lsof -i -n -P
COMMAND    PID        USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
sshd      3028        root    3u  IPv4   7072      0t0  TCP *:22 (LISTEN)
sshd      3028        root    4u  IPv6   7074      0t0  TCP *:22 (LISTEN)

iproute2's ss can do this, too (as root):

# ss -lp
State      Recv-Q Send-Q      Local Address:Port          Peer Address:Port   
LISTEN     0      128                    :::ssh                     :::*        users:(("sshd",3028,4))
LISTEN     0      128                     *:ssh                      *:*        users:(("sshd",3028,3))

...and finally, netstat (as root):

# netstat -lp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 *:ssh                   *:*                     LISTEN      3028/sshd  

As far as i know, you can't (except on BSD systems, where Finkregh's solution works fine). It might be possible but you don't care, because most application listen on every interface, even when bound to an IP address.

On linux (and openwrt), the only way for an application to listen only on a certain interface is the SO_BINDTODEVICE socket option. Few applications actually supports this, as it is OS specific. That, or they use packet socket, but that's for low level protocols (like dhcp servers).

On linux, which uses a weak host model, every application listens on every interfaces by default, even when binding a socket to an IP address. The only exception is when binding to 127.0.0.1, which ensures that the application only listens on the lo interface.

You heard it right: If you have two interfaces (say eth0 and eth1) with two different IP addresses, (say 192.0.2.1 for eth0 and 198.51.100.1 for eth1) and you tell an application to bind on 192.0.2.1, the application will still listen on both interfaces, but will only respond if the destination IP is 192.0.2.1. So someone on the eth1 interface, if its routing table is appropriately defined, can access your application by accessing it via the 192.0.2.1 address (but not via 198.51.100.1) on the eth1 interface.

Assuming that binding to an IP address is the same as binding to a network interface is utterly false on Linux. If that bothers you, use policy routing and/or iptables.

Tags:

Daemon

Netstat