Ger*_*zty 5 sockets linux networking bind
如果一个套接字被创建,绑定和监听,而不是它列出netstat -l
,可见/proc/net/<L4 type>
,等等.这没关系.
但是,如果套接字仅创建并绑定到特定的TCP/UDP/SCTP端口和IP,则在上述位置不可见./proc/<PID>/fd/
使用socket:[inode]
符号可以看到fd ,但它不能与任何其他表/列表AFAIK相关联.问题是,绑定套接字会阻止同一网络命名空间中的其他进程在同一IP /端口上绑定/侦听.它导致了Errno 98: Address already in use
.
那么,是否可以列出(或确定所有者进程)绑定,但不是监听/连接套接字?
编辑:
我们来看看这个Golang TCP示例.你可以运行它go run TCP_bind.go
.如果运行两次,则第二次运行失败.
您如何判断流程绑定到哪个端口?或者反过来,当你不能在你的应用程序中使用它时,你怎么能找到谁保留端口55555?
在 Linux 下,您可以使用审核系统来记录某些事件,其中包括系统调用。我们可以利用它来找出哪个进程调用了bind(2)。
假设Ubuntu:
sudo apt install auditd
sudo auditctl -a exit,always -F arch=b64 -S bind -k BIND
Run Code Online (Sandbox Code Playgroud)
我已经使用以下 Python 代码进行了测试,相当于您的 Go 代码:
import socket
s = socket.socket()
s.bind(('127.0.0.1', 55555))
Run Code Online (Sandbox Code Playgroud)
可以通过以下方式搜索审核日志ausearch -i -k BIND
:
----
type=CONFIG_CHANGE msg=audit(04/18/2017 21:29:52.730:19) : auid=ovi ses=1 op="add_rule" key=BIND list=exit res=yes
----
type=CONFIG_CHANGE msg=audit(04/18/2017 21:29:58.062:20) : auid=ovi ses=1 op="add_rule" key=BIND list=exit res=yes
----
type=PROCTITLE msg=audit(04/18/2017 21:31:09.189:33) : proctitle=python
type=SOCKADDR msg=audit(04/18/2017 21:31:09.189:33) : saddr=inet host:127.0.0.1 serv:55555
type=SYSCALL msg=audit(04/18/2017 21:31:09.189:33) : arch=x86_64 syscall=bind success=yes exit=0 a0=0x3 a1=0x7fff11c66440 a2=0x10 a3=0x373 items=0 ppid=28677 pid=28693 auid=o9000 uid=o9000 gid=o9000 euid=o9000 suid=o9000 fsuid=o9000 egid=o9000 sgid=o9000
fsgid=o9000 tty=pts1 ses=4 comm=python exe=/usr/bin/python2.7 key=BIND
Run Code Online (Sandbox Code Playgroud)
我们确实可以看到一个从 pid 28693 调用 host:127.0.0.1 serv:55555 的绑定。
必须在启动有问题的程序之前启用审核。
实际日志存储在/var/log/audit/audit.log
. 您可能需要设置auditd来轮换它,这样它就不会无限期地增长。
上述命令的解释(基于doc):
auditctl -a
:审核系统调用...exit,always
:在系统调用退出时始终对其进行审核(因为我们想知道是否bind(2)
成功)-F arch=b64
:审核 64 位程序(必须为 32 位创建单独的规则!)-S bind
:审计bind
系统调用-k BIND
BIND
:为日志中的事件添加标签ausearch
:搜索审核日志...-i
:将结构转换为人类可读的符号(解码IP地址和端口号)-k BIND
:仅显示标记为“BIND”的事件。