服务器商家后台显示机器用了很多流量,
但不知道这些流量是哪个服务、哪个端口产生的。
一台服务器上可能同时跑着:
如果只看总流量,很难判断到底是谁消耗了流量。
这个时候就可以用 iptables / ip6tables 做按端口流量统计。
一、基本思路
Linux 的 iptables 规则本身就带有计数器。
每一条规则都会记录:
所以我们可以创建一组专门用于统计的规则。
让流量经过这些规则,但不拦截、不放行、不改变原有防火墙逻辑。
只用它们的计数器来统计流量。
核心思路是:
指定端口流量 -> 单独统计未知端口流量 -> 归到 OTHER只统计外网网卡 -> 排除 127.0.0.1 本地回环流量IPv4 用 iptablesIPv6 用 ip6tables
二、先确认外网网卡
先查看服务器默认出口网卡:
示例输出:
default via 10.57.68.1 dev eth0 proto dhcp src 10.57.68.55
其中:
说明外网网卡是 eth0。
后面的规则都只统计 eth0,这样可以避免把 127.0.0.1、本机端口转发、本地 DNS 等回环流量误算进去。
三、查看当前机器有哪些端口在监听
在配置统计前,建议先查看当前服务器有哪些服务正在监听端口:
这个命令可以看到:
比如:
tcp LISTEN 0 128 0.0.0.0:22 users:(("sshd",pid=150,fd=3))tcp LISTEN 0 128 127.0.0.1:8080 users:(("ssh",pid=1918,fd=5))udp UNCONN 0 0 0.0.0.0:41641 users:(("tailscaled",pid=1166,fd=19))
这里要区分两类端口:
1. 公网监听端口
例如:
0.0.0.0:22[::]:220.0.0.0:41641
这些端口可能产生公网流量,值得统计。
2. 本机回环端口
例如:
127.0.0.1:8080127.0.0.53:53[::1]:8080
这些只在本机内部使用,不应该算作公网月流量。
所以按端口统计流量时,最好配合网卡参数:
只统计外网网卡流量。
四、创建按端口统计规则
下面是一份完整示例。
假设外网网卡是 eth0。
统计的已知端口包括:
TCP:22, 53, 80, 443, 2053, 2083, 2087, 2096, 8080, 8443, 5355UDP:53, 443, 8443, 36409, 41641, 5355
其中:
22 SSH53 DNS80/443 Web41641 Tailscale5355 systemd-resolve / LLMNR36409 自定义 UDP 服务示例
可以根据自己的机器情况修改端口列表。
执行:
IFACE=eth0TCP_PORTS="22 53 80 443 2053 2083 2087 2096 8080 8443 5355"UDP_PORTS="53 443 8443 36409 41641 5355"echo "当前统计网卡: $IFACE"echo "TCP端口: $TCP_PORTS"echo "UDP端口: $UDP_PORTS"# 创建 IPv4 统计链iptables -N PORT_TRAFFIC_IN 2>/dev/nulliptables -N PORT_TRAFFIC_OUT 2>/dev/null# 创建 IPv6 统计链ip6tables -N PORT_TRAFFIC_IN 2>/dev/nullip6tables -N PORT_TRAFFIC_OUT 2>/dev/null# 把统计链挂到 INPUT / OUTPUTiptables -C INPUT -j PORT_TRAFFIC_IN 2>/dev/null || iptables -I INPUT -j PORT_TRAFFIC_INiptables -C OUTPUT -j PORT_TRAFFIC_OUT 2>/dev/null || iptables -I OUTPUT -j PORT_TRAFFIC_OUTip6tables -C INPUT -j PORT_TRAFFIC_IN 2>/dev/null || ip6tables -I INPUT -j PORT_TRAFFIC_INip6tables -C OUTPUT -j PORT_TRAFFIC_OUT 2>/dev/null || ip6tables -I OUTPUT -j PORT_TRAFFIC_OUT# 清空旧统计规则iptables -F PORT_TRAFFIC_INiptables -F PORT_TRAFFIC_OUTip6tables -F PORT_TRAFFIC_INip6tables -F PORT_TRAFFIC_OUT# IPv4 TCP 端口统计for port in $TCP_PORTS; do iptables -A PORT_TRAFFIC_IN -i "$IFACE" -p tcp --dport "$port" -j RETURN iptables -A PORT_TRAFFIC_OUT -o "$IFACE" -p tcp --sport "$port" -j RETURNdone# IPv4 UDP 端口统计for port in $UDP_PORTS; do iptables -A PORT_TRAFFIC_IN -i "$IFACE" -p udp --dport "$port" -j RETURN iptables -A PORT_TRAFFIC_OUT -o "$IFACE" -p udp --sport "$port" -j RETURNdone# IPv4 OTHER:其他端口总流量iptables -A PORT_TRAFFIC_IN -i "$IFACE" -m comment --comment "OTHER" -j RETURNiptables -A PORT_TRAFFIC_OUT -o "$IFACE" -m comment --comment "OTHER" -j RETURN# IPv6 TCP 端口统计for port in $TCP_PORTS; do ip6tables -A PORT_TRAFFIC_IN -i "$IFACE" -p tcp --dport "$port" -j RETURN ip6tables -A PORT_TRAFFIC_OUT -o "$IFACE" -p tcp --sport "$port" -j RETURNdone# IPv6 UDP 端口统计for port in $UDP_PORTS; do ip6tables -A PORT_TRAFFIC_IN -i "$IFACE" -p udp --dport "$port" -j RETURN ip6tables -A PORT_TRAFFIC_OUT -o "$IFACE" -p udp --sport "$port" -j RETURNdone# IPv6 OTHER:其他端口总流量ip6tables -A PORT_TRAFFIC_IN -i "$IFACE" -m comment --comment "OTHER" -j RETURNip6tables -A PORT_TRAFFIC_OUT -o "$IFACE" -m comment --comment "OTHER" -j RETURN# 清零,从当前时刻重新开始统计iptables -Z PORT_TRAFFIC_INiptables -Z PORT_TRAFFIC_OUTip6tables -Z PORT_TRAFFIC_INip6tables -Z PORT_TRAFFIC_OUT
五、为什么要加 OTHER?
如果只统计指定端口,比如只统计:
那么如果有其他端口突然产生大量流量,比如:
你是看不到的。
所以建议在最后加一条 OTHER 统计规则。
这样结果会分成两类:
如果后面发现:
就说明有未列入统计的端口在跑流量,需要继续排查。
六、创建查看脚本
直接查看 iptables -L 输出比较难读,可以创建一个脚本,把 bytes 自动换算成 MB 和 GB。
创建脚本:
cat > /usr/local/bin/port-traffic <<'EOF'#!/bin/bashshow_chain() { local CMD="$1" local IPVER="$2" local DIR="$3" local CHAIN="$4" $CMD -L "$CHAIN" -v -n -x 2>/dev/null | awk -v ipver="$IPVER" -v dir="$DIR" ' /dpt:|spt:|OTHER/ { bytes=$2 if ($0 ~ /tcp/) proto="tcp" else if ($0 ~ /udp/) proto="udp" else proto="all" if ($0 ~ /OTHER/) { port="OTHER" } else { port=$NF sub("dpt:","",port) sub("spt:","",port) } printf "%-5s %-6s %-4s %-8s %15d bytes %10.2f MB %10.4f GB\n", ipver, dir, proto, port, bytes, bytes/1024/1024, bytes/1024/1024/1024 }'}echo "IP版本 方向 协议 端口 bytes MB GB"echo "--------------------------------------------------------------------------"show_chain iptables IPv4 入站 PORT_TRAFFIC_INshow_chain iptables IPv4 出站 PORT_TRAFFIC_OUTshow_chain ip6tables IPv6 入站 PORT_TRAFFIC_INshow_chain ip6tables IPv6 出站 PORT_TRAFFIC_OUTEOF
chmod +x /usr/local/bin/port-traffic
以后直接执行:
示例输出:
IP版本 方向 协议 端口 bytes MB GB--------------------------------------------------------------------------IPv4 入站 tcp 22 7440 bytes 0.01 MB 0.0000 GBIPv4 出站 tcp 22 13100 bytes 0.01 MB 0.0000 GBIPv4 入站 all OTHER 6870 bytes 0.01 MB 0.0000 GBIPv4 出站 all OTHER 5256 bytes 0.01 MB 0.0000 GBIPv6 入站 all OTHER 1328 bytes 0.00 MB 0.0000 GBIPv6 出站 all OTHER 1216 bytes 0.00 MB 0.0000 GB
七、如何理解统计结果?
1. 入站和出站都要看
服务商一般统计的是总流量,通常要看:
比如:
IPv4 入站 tcp 443:10GBIPv4 出站 tcp 443:90GB
那么 443 端口大概用了:
2. SSH 有少量流量是正常的
只要你正在登录服务器,22/tcp 就会一直有少量流量:
IPv4 入站 tcp 22IPv4 出站 tcp 22
这属于正常情况。
3. OTHER 很小不用管
如果 OTHER 只有几 KB、几 MB,一般是系统正常通信或零散流量。
如果 OTHER 很大,比如几百 MB、几 GB、几十 GB,就要排查未知端口。
八、排查 OTHER 流量
如果发现 OTHER 很大,可以先看当前监听端口:
也可以实时查看端口连接流量:
apt install -y iftopiftop -i eth0 -P
其中:
表示指定外网网卡。
表示显示端口。
这样可以看到当前哪些连接、哪些端口正在跑流量。
九、清零重新开始统计
如果想从当前时间重新开始统计,可以执行:
iptables -Z PORT_TRAFFIC_INiptables -Z PORT_TRAFFIC_OUTip6tables -Z PORT_TRAFFIC_INip6tables -Z PORT_TRAFFIC_OUT
然后再查看:
十、持久化保存规则
默认情况下,iptables 规则重启后可能丢失。
Debian / Ubuntu 可以安装:
apt updateapt install -y iptables-persistent
安装过程中如果询问:
Save current IPv4 rules?Save current IPv6 rules?
都选择:
之后手动保存:
netfilter-persistent save
看到类似输出:
run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables saverun-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables save
说明 IPv4 和 IPv6 规则都保存成功了。
十一、这种方式的优缺点
优点
不需要额外安装复杂监控系统直接利用 iptables 自带计数器可以同时统计 IPv4 和 IPv6可以按端口区分流量可以排除本机回环流量可以增加 OTHER 发现未知端口流量
缺点
每台机器都要单独配置只能统计本机流量端口列表需要根据服务情况维护不能直接显示历史曲线规则重启后需要持久化保存
总结
按端口统计 VPS 流量的一种实用方案:
iptables / ip6tables 统计链指定外网网卡常用端口单独统计未知端口归到 OTHERport-traffic 脚本格式化输出netfilter-persistent 持久化保存
这样既能知道 22、443、8443、41641 等端口分别用了多少流量,
也能通过 OTHER 发现未知端口是否在偷偷跑流量。
对于日常排查 VPS 月流量、Tailscale 流量、Web 服务流量,这种方式已经足够实用。