本文博主介绍的这个 iptables 配置实现了完整的NAT网关功能,让内网设备共享一个公网IP上网,并能将公网服务映射到内网服务器。
# 1. 开启IP转发echo1>/proc/sys/net/ipv4/ip_forward# 2. 设置SNAT(内网访问外网)# eth0: 公网接口,eth1: 内网接口iptables -t nat -A POSTROUTING -o eth0 -s192.168.1.0/24 -j MASQUERADE# 或使用固定公网IPiptables -t nat -A POSTROUTING -o eth0 -s192.168.1.0/24 -j SNAT --to-source 公网IP# 3. 设置DNAT(外网访问内网服务器)# 将公网IP的80端口映射到内网Web服务器iptables -t nat -A PREROUTING -i eth0 -p tcp --dport80-j DNAT --to-destination192.168.1.100:80# 4. 允许转发流量iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -s192.168.1.0/24 -j ACCEPT网络地址转换(NAT)网关配置详解
一、基础概念:什么是网关?
内网设备 → 网关 → 外网(互联网) ↓ ↓ 192.168.1.x 公网IP网关负责内网和外网之间的桥梁,解决内网设备无法直接访问互联网的问题。
二、解释脚本
1. 开启IP转发
echo1>/proc/sys/net/ipv4/ip_forward作用:让Linux变成路由器,能转发数据包
比喻:
- 默认:Linux是个"死胡同",数据包进来只能给本机
- 开启后:Linux变成"十字路口",可以转发数据到其他地方
永久生效:
# 编辑配置文件echo"net.ipv4.ip_forward = 1">>/etc/sysctl.conf sysctl -p2. SNAT:内网访问外网(出站)
iptables -t nat -A POSTROUTING -o eth0 -s192.168.1.0/24 -j MASQUERADE场景:内网电脑(192.168.1.10)访问百度
处理过程:
发送时: 源IP: 192.168.1.10 → 源IP: 公网IP 目的IP: 百度IP → 目的IP: 百度IP 返回时: 源IP: 百度IP → 源IP: 百度IP 目的IP: 公网IP → 目的IP: 192.168.1.10参数解释:
-t nat:使用nat表(专门改IP地址)-A POSTROUTING:在路由后修改(出门前改寄件人地址)-o eth0:从eth0网卡出去(公网接口)-s 192.168.1.0/24:源IP是内网段-j MASQUERADE:自动伪装成出口IP
MASQUERADE vs SNAT:
# MASQUERADE(推荐动态IP,如PPPoE拨号)iptables -t nat -A POSTROUTING -o ppp0 -s192.168.1.0/24 -j MASQUERADE# 自动获取出口IP,适合IP会变的情况# SNAT(固定公网IP)iptables -t nat -A POSTROUTING -o eth0 -s192.168.1.0/24 -j SNAT --to-source203.0.113.10# 明确指定公网IP3. DNAT:外网访问内网服务器(入站)
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport80-j DNAT --to-destination192.168.1.100:80场景:外网用户访问公网IP的80端口,转到内网Web服务器
处理过程:
用户访问: 请求: 公网IP:80 → 转发到: 192.168.1.100:80 服务器回复时自动通过SNAT返回参数解释:
-A PREROUTING:在路由前修改(进门时就改目的地)-i eth0:从eth0进来(公网接口)--dport 80:目标端口是80(HTTP)-j DNAT:目的地址转换--to-destination:转到哪个内网服务器
端口映射例子:
# Web服务器iptables -t nat -A PREROUTING -i eth0 -p tcp --dport80-j DNAT --to192.168.1.100:80# SSH服务器(外网用2222端口,内网用22端口)iptables -t nat -A PREROUTING -i eth0 -p tcp --dport2222-j DNAT --to192.168.1.101:22# 游戏服务器iptables -t nat -A PREROUTING -i eth0 -p udp --dport27015-j DNAT --to192.168.1.102:270154. 允许转发流量(FORWARD链)
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -s192.168.1.0/24 -j ACCEPT为什么需要:
- 开启了IP转发,但iptables默认阻止所有转发
- 需要明确允许哪些流量可以转发
第一条:允许响应数据
-m state --state ESTABLISHED,RELATED -j ACCEPT允许已建立连接和相关连接的数据包,确保内网访问外网的回复能回来
第二条:允许内网主动访问外网
-s192.168.1.0/24 -j ACCEPT允许内网段(192.168.1.0/24)发起的流量转发出去
注意:外网主动访问内网不需要单独允许,因为DNAT会自动处理
三、完整数据流示例
场景1:内网电脑访问百度
1. 内网电脑(192.168.1.10) → 网关 → 外网 src: 192.168.1.10 SNAT src: 公网IP dst: 百度IP ↓ dst: 百度IP 2. 百度回复 → 网关 → 内网电脑 src: 百度IP DNAT src: 百度IP dst: 公网IP ↓ dst: 192.168.1.10场景2:外网用户访问内网Web服务器
1. 外网用户 → 网关 → 内网服务器 src: 用户IP DNAT src: 用户IP dst: 公网IP:80 ↓ dst: 192.168.1.100:80 2. 服务器回复 → 网关 → 外网用户 src: 192.168.1.100 SNAT src: 公网IP dst: 用户IP ↓ dst: 用户IP四、双网卡典型网络拓扑
eth1 (内网) ↓ 外网 ← eth0 (公网) [网关服务器] → 内网设备 ↑ 192.168.1.1/24 内网设备配置: IP: 192.168.1.x/24 网关: 192.168.1.1 DNS: 114.114.114.114五、常用检查命令
# 1. 检查IP转发是否开启cat/proc/sys/net/ipv4/ip_forward# 显示1表示开启# 2. 查看NAT规则iptables -t nat -L -n -v# 3. 查看连接追踪cat/proc/net/nf_conntrack|head-20# 4. 测试内网能否上网ping-c38.8.8.8# 5. 测试端口映射telnet 公网IP80六、安全增强建议
# 1. 限制内网某些IP不能上网iptables -t nat -A POSTROUTING -o eth0 -s192.168.1.50 -j DROP# 2. 限制外网只能访问特定端口iptables -A FORWARD -i eth0 -o eth1 -p tcp --dport80-j ACCEPT iptables -A FORWARD -i eth0 -o eth1 -p tcp --dport443-j ACCEPT iptables -A FORWARD -i eth0 -o eth1 -j DROP# 3. 防止内网滥用(限速)tc qdiscadddev eth0 root handle1: htb default30tc classadddev eth0 parent1: classid1:1 htb rate 100mbit tc classadddev eth0 parent1:1 classid1:10 htb rate 1mbit ceil 5mbit iptables -t mangle -A POSTROUTING -s192.168.1.10 -j CLASSIFY --set-class1:10七、问题排查
问题1:内网能ping通外网但打不开网页
# 检查DNSiptables -A FORWARD -p udp --dport53-j ACCEPT iptables -A FORWARD -p tcp --dport53-j ACCEPT# 内网设备DNS设置为:8.8.8.8 或 114.114.114.114问题2:端口映射不生效
# 1. 检查服务是否监听正确IPnetstat-tlnp|grep:80# 2. 检查FORWARD链是否允许iptables -L FORWARD -n# 3. 关闭网关本机防火墙(临时测试)iptables -P INPUT ACCEPT问题3:连接数太多导致卡顿
# 调整连接跟踪表大小echo65536>/proc/sys/net/nf_conntrack_maxecho180>/proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established