怎么读 ss 的输出,以及绑定地址的陷阱
一句话总结
ss -ltnp一句话说,如果忽略了“在听什么”和“在听谁”,那么远程连接故障就有一半是由于忽略了后者。
为什么需要这个?
让我们看看最常见的分配事故。
LISTEN 0 4096 127.0.0.1:8080 0.0.0.0:* users:(("api",pid=1,fd=7))
这个过程只在回环中听。在同一个主机上curl localhost:8080成功了。但是用其他主机或pad IP连接的话,内核会以RST拒绝。也就是说,会出现connection refused。
在这里判断分歧。用pad IP的话是refused,但如果pad内部用localhost的话成功的话,原因不是网络政策,而是绑定地址。相反,如果用pad IP的话也是timeout的话,从那时开始看NetworkPolicy和CNI。这一次分歧将调查范围缩小了一半。
每个框架都确定了容易犯错的点。
| 框架 | 安全的标记 | 错误标记 |
|---|---|---|
| Express | app.listen(8080) |
app.listen(8080, '127.0.0.1') |
| Go net/http | ":8080" |
"localhost:8080" |
| Gunicorn | --bind 0.0.0.0:8000 |
--bind 127.0.0.1:8000 |
| Rails | -b 0.0.0.0 |
基本值(仅限本地) |
| PostgreSQL | listen_addresses = '*' |
基本值localhost |
怎么行动
ss的选项是数一数二的。
ss -ltnp # 리슨 중인 TCP + 프로세스
ss -tulpn # TCP/UDP 리슨 전체
ss -s # 소켓 총계 (누수 판별)
ss -tan state established # 확립된 연결만
ss -tanp state syn-sent # 나갔는데 응답 없는 연결
ss -tnio # rto/rtt/cwnd 같은 타이머까지
选项的意思:-tTCP,-uUDP,-l李森万,-a全部,-n不解释名字,-p过程。
**Recv-Q和Send-Q根据状态会有不同的含义。**这个经常出现在考试中。
| 套接字状态 | Recv-Q | Send-Q |
|---|---|---|
| LISTEN | accept 等待中的完成队列长度 | 后台日志最大值 |
| ESTABLISHED | 尚未读取的接收数据 | 尚未确认的发送数据 |
LISTEN套接字的Recv-Q与Send-Q相连的话,意味着accept队列满了。这时nstat -az | grep -E 'ListenOverflows|ListenDrops'如果增加的话,不是网络而是应用程序处理量的原因。无论如何搜索防火墙都找不到。
整理一下按TCP状态进行的运营评价吧。
CLOSE_WAIT过度→应用程序不关闭套接字(fd泄漏)SYN_RECV过度→怀疑SYN floodTIME_WAIT过量→正常2MSL等待。只有当端口实际耗尽时才会进行对应
/proc/net/tcp也最好知道直接读的方法。在没有工具的最小容器中成为最后的手段。本地地址是小端16进制,端口也是16进制(8080 =1F90),状态栏的0A是LISTEN。
在现场相遇的样子
**将refused归咎于防火墙的吴珍。**实际防火墙几乎总是DROP政策,所以被阻止的端口会进入timeout。除非故意使用了回RST的REJECT规则,否则refused的意思是“已经走了,但没有人听”。
**当Kubernetes Endpoints为空时。**如果附加到服务IP上,就会立即被拒绝。kubectl get endpoints <svc>去<none>如果这个,选择器不对,或者readynessProbe正在失败。不是网络的问题,是标签的问题。
ss按一行缩小的顺序
查看网络问题时netstat相反ss使用的话,可以快速提取所需的内容。
有。如果确定经常使用的形式,调查时间就会大大缩短。
ss -tlnp # 듣고 있는 TCP 와 그 프로세스
ss -tanp state established '( dport = :5432 or sport = :5432 )'
ss -s # 상태별 요약
ss -tin # rtt, cwnd, 재전송 — 성능을 볼 때
在听筒上Recv-Q/Send-Q的意思不同。在连接的插座上,分别
虽然是未读的数据和未发送的数据,但在听取的套接字中,目前accept队列
是长度和其上限。如果两个数字相连的话,应用程序就无法接收连接。
是中,这时内核会丢弃完成的连接。
nstat -az | grep -E 'ListenDrops|ListenOverflows|TCPBacklogDrop'
看看在哪里绑定了。127.0.0.1:8080不能从外面进来。集装箱
最常见的情况是将数据包绑定在内部的环形包中,然后说“端口无法打开”。
0.0.0.0伊娜*要出来才能在外面接触到。
连接在哪个状态下停止是决定原因的。
| 状态 | 意思 |
|---|---|
SYN-SENT积攒 |
对方不回应(防火墙安静地被抛弃) |
SYN-RECV堆积 |
我们这边accept队列或SYN队列问题 |
CLOSE-WAIT堆积 |
我们的应用程序不会close() |
FIN-WAIT-2积攒 |
对方不关闭 |
TIME-WAIT很多 |
正常。60秒后消失 |
CLOSE-WAIT不是内核,而是指唯一指代我们代码的错误的状态。
特别重要。时间流逝也不会消失。
区分拒绝和无回应。Connection refused甚至去了对方主机
那个端口没有打开,超时是因为数据包丢失在某个地方。前面
的是服务问题,后面的是路由和防火墙问题。
下次实习要做的事情
启动两个服务器,但其中一个是0.0.0.0,一个是127.0.0.1然后绑定。然后用自己的IP敲打两个端口,直接制作为什么哪一个失败。/proc/net/tcp也用手读。