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:
*:22
listen on port 22 on every available IPv4 address:::22
listen on port 22 on every available IP address (i do not write IPv6, as IP is IPv6 per RFC 6540)127.0.0.1:6010
listen on IPv4 address 127.0.0.1 (localhost/loopback) and port 6010::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
.