《没有架构图?用 netstat、ss、tcpdump 还原服务连接与数据流向》

📢 你是否遇到过这些问题?

  • 接手一个老项目,只有服务器账号,没有架构图?
  • 服务突然异常,但不知道它依赖哪些外部系统?
  • 想画数据流向图,却找不到文档?

别担心!只要你有 shell 权限,就能用几个 Linux 命令,逆向还原出整个系统的通信拓扑

本文将带你一步步:

  1. 查看谁在监听
  2. 分析谁在连接你
  3. 抓包看 UDP 数据来源
  4. 统计出站连接目标
  5. 最终拼出一张"事实上的架构图"

无需任何外部工具,全是系统自带命令(netstatsslsoftcpdump),拿来即用,实战有效

💡 适用场景:运维排查、系统交接、安全审计、自研服务调试

本文帮你彻底搞懂:如何排查"谁在连我"、"我连了谁",适用于 Java、Nginx、MySQL、自研服务等所有网络程序


一、核心概念:先搞懂这些术语

概念 说明
监听端口(LISTEN) 你的服务正在等待别人来连接(如 Web 服务监听 80)
入站连接(Inbound) 外部机器连接你的服务 → "谁在连我"
出站连接(Outbound) 你的程序主动连接外部服务 → "我连了谁"
UDP 通信 UDP 是无连接协议,没有"连接状态",只能通过抓包看"谁发了包给我"

📌 关键区别

  • TCP 有连接状态(ESTABLISHED, LISTEN),可直接查
  • UDP 无连接,必须用 tcpdump 抓包分析

二、常用命令速查表(建议收藏)

目的 命令
查看所有监听端口 ss -lntupnetstat -lntup
查看某进程的连接 lsof -p <PID>
查看谁在连某个端口 `ss -tnp
抓包看 UDP 谁在发数据 tcpdump -i any -n udp dst port <端口>
统计连接来源 IP `ss -tn

✅ 推荐使用 ss 替代老旧的 netstat(更快、更现代)


三、如何查看"我的程序被谁连接"(入站连接)

1. 查看本机监听了哪些端口

bash 复制代码
ss -lntup
# 或(旧系统)
netstat -lntup

输出示例:

text 复制代码
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program
tcp6       0      0 10.104.2.184:20007      :::*                    LISTEN      1182/java
udp6       0      0 10.104.2.184:20009      :::*                                1182/java

👉 说明:

  • java 进程(PID 1182)在监听 20007(TCP)和 20009(UDP)
  • 10.104.2.184 是内网 IP,表示允许内网访问

2. 查看谁在连接 TCP 端口(如 20007)

bash 复制代码
ss -tnp | grep ':20007'

输出示例:

text 复制代码
ESTAB 0 0 10.104.2.184:20007 10.104.11.178:51865 users:(("java",pid=1182,fd=12))

👉 说明:

  • 10.104.11.178 正在连接你的 20007 端口
  • 这是典型的"服务间调用"场景

3.ss 命令参数详解

ss 的参数是 单字母选项,可以组合使用。以下是常见参数说明:

参数 全称(含义) 说明
-l --listening 显示监听状态的端口(LISTEN)
-n --numeric 显示数字形式的地址和端口,不解析成域名或服务名(如不把 80 解析为 http)
-t --tcp 显示 TCP 协议的连接
-u --udp 显示 UDP 协议的连接
-p --processes 显示使用该连接的进程信息(PID 和程序名)

3. 查看谁在向 UDP 端口发数据(如 20009)

UDP 没有"连接状态",必须用 tcpdump 抓包:

bash 复制代码
tcpdump -i any -n -c 10 'udp and dst port 20009'

输出示例:

text 复制代码
IP 10.104.11.178.51865 > 10.104.2.184.20009: UDP, length 1440
IP 10.104.33.6.59928 > 10.104.2.184.20009: UDP, length 144

👉 说明:

  • 10.104.11.17810.104.33.6 正在向你发送数据
  • 你的服务是 UDP 服务端(如心跳、配置同步)

4. 抓多个 UDP 端口(批量监控)

bash 复制代码
tcpdump -i any -n -c 10 'udp and (port 20009 or port 20010 or port 20012 or port 20013)'

⚠️ 注意:不要写成 200010(这是 20万10),正确是 20010(2万零10)


5. 只看"入站"流量(别人发给你)

bash 复制代码
# 只抓目标是你服务器的包
tcpdump -i any -n 'udp and (dst port 20009 or dst port 20010)'

6. 排除自己发出的包(避免干扰)

bash 复制代码
# 排除从本机发出的 UDP 包
tcpdump -i any -n 'udp and (port 20009 or port 20010) and not src host 10.104.2.184'

7. 统计 UDP 数据来源 IP(批量分析)

bash 复制代码
timeout 10 tcpdump -i any -n -nn -l udp 'dst port 20009' 2>/dev/null | \
awk '{print $3}' | cut -d'>' -f1 | sort | uniq -c | sort -nr

输出:

text 复制代码
     8 10.104.11.178
     5 10.104.33.6
     3 10.104.5.35

👉 表示:

  • 10.104.11.178 发了 8 次包,是主要客户端

四、如何查看"我的程序连接了谁"(出站连接)

1. 使用 lsof 查看某进程的连接

bash 复制代码
lsof -p 1182 | grep ESTABLISHED

输出示例:

text 复制代码
java 1182 root 15u IPv6 123456 0t0 TCP 10.104.2.184:54220->10.104.7.2:20009 (ESTABLISHED)

👉 说明:

  • 你的 Java 程序正在连接 10.104.7.2:20009
  • 这可能是上报、转发或服务发现

2. 使用 ss 查看出站连接

bash 复制代码
ss -tnp | grep '1182'

或按目标 IP/端口过滤:

bash 复制代码
ss -tnp | grep '10.104.7.2:20009'

3. 使用 netstat(旧系统)

bash 复制代码
netstat -tnp | grep 1182

五、tcpdump 实战:谁在连接我?我在连谁?

场景 1:抓"谁在连我"(入站)

bash 复制代码
# TCP:谁在连接我的 20007 端口(SYN 包)
tcpdump -i any -n 'tcp and dst port 20007 and (tcp[tcpflags] & tcp-syn) != 0'

# UDP:谁在向 20009 发包
tcpdump -i any -n 'udp and dst port 20009'

场景 2:抓"我在连谁"(出站)

bash 复制代码
# 我的程序从本地 54220 端口发起连接
tcpdump -i any -n 'src port 54220'

# 或看我连了哪个外部 IP
tcpdump -i any -n 'dst host 10.104.7.2'

场景 3:监控双向通信

bash 复制代码
# 监控与某个服务的全部通信
tcpdump -i any -n 'host 10.104.7.2 and port 20009'

六、一键诊断脚本:check_connections.sh

bash 复制代码
#!/bin/bash
echo "=== 当前时间 ==="
date

echo -e "\n=== 监听端口 ==="
ss -lntup

echo -e "\n=== TCP 入站连接统计(来源 IP)==="
ss -tn | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head -10

echo -e "\n=== UDP 数据来源(最近10秒)==="
echo "抓包中...(请稍等)"
timeout 10 tcpdump -i any -n -nn -l udp 'dst port 20009 or dst port 20010' 2>/dev/null | \
awk '{print $3}' | cut -d'>' -f1 | sort | uniq -c | sort -nr || echo "无 UDP 流量"

echo -e "\n=== 出站连接(ESTABLISHED)==="
ss -tn | grep ESTAB | awk '{print $5}' | sort | uniq -c | sort -nr | head -10

echo -e "\n=== 本地监听服务 ==="
ss -lntup | grep -v '127.0.0.1' | grep -v '::1' || echo "无非本地监听"

使用方法:

bash 复制代码
chmod +x check_connections.sh
./check_connections.sh  

七、附录:常见端口用途参考

端口 协议 常见用途
22 TCP SSH
80/443 TCP HTTP/HTTPS
3306 TCP MySQL
6379 TCP Redis
9092 TCP Kafka
20007~20013 UDP/TCP 自定义监控、游戏、配置服务

总结:一句话记住

你想知道 使用命令
我监听了哪些端口? ss -lntup
谁在连我的 TCP 服务? `ss -tnp
谁在向我的 UDP 端口发数据? tcpdump -i any -n udp dst port <端口>
我的程序连接了谁? lsof -p <PID>ss -tnp
统计连接来源? ss / tcpdump + awk + sort + uniq
相关推荐
千钰v3 小时前
Tcpdump: The Basics Tcpdump 基础
linux·运维·网络·tcpdump·tryhackme
全栈技术负责人3 小时前
前端网络性能优化实践:从 HTTP 请求到 HTTPS 与 HTTP/2 升级
前端·网络·http
独行soc3 小时前
2025年渗透测试面试题总结-67(题目+回答)
网络·python·安全·web安全·网络安全·adb·渗透测试
eybk4 小时前
用python的socket写一个局域网传输文件的程序
服务器·网络·python
树码小子4 小时前
Java网络编程:(socket API编程:UDP协议的 socket API -- 回显程序的服务器端程序的编写)
java·网络·udp
云深麋鹿5 小时前
数据链路层总结
java·网络
威斯软科的老司机5 小时前
WebSocket压缩传输优化:机器视觉高清流在DCS中的低延迟方案
网络·websocket·网络协议
小狮子安度因6 小时前
AAC ADTS格式分析
网络·ffmpeg·aac
啟明起鸣7 小时前
【网络编程】从与 TCP 服务器的对比中探讨出 UDP 协议服务器的并发方案(C 语言)
服务器·c语言·开发语言·网络·tcp/ip·udp