将要介绍的防火墙工具iptables,内核实现的软件防火墙,内核根据iptables的规则实现netfilter。先来看看防火墙的流程介绍。
主要由4表5链构成:
大概意思就是:在每条链上添加上述4表的规则,来实现报文过滤转发等功能。
上图的上部分就是主机防火墙的工作流程。
1、常用操作
#查看
[root@node3 ~]# iptables -vnL [--line-numbers] # v vv vvv
#清空数据
[root@node3 ~]# iptables -Z [chain]
#删除 规则
[root@node3 ~]# iptables -D chain num
#清空所有规则
[root@node3 ~]# iptables -F [chain]
#创建删除自定义chain 不能删除被正在被引用的chain
[root@localhost ~]# iptables -N in_web_rule
[root@localhost ~]# iptables -t in_web_rule
[root@localhost ~]# iptables -X in_web_rule
1.1 初始化 开放ssh,设置白名单
[root@node3 ~]# iptables -I INPUT -p tcp --dport 22 -j ACCEPT
[root@node3 ~]# iptables -I OUTPUT -p tcp --sport 22 -j ACCEPT
[root@node3 ~]# iptables -P FORWARD DROP
[root@node3 ~]# iptables -A INPUT -j REJECT
[root@node3 ~]# iptables -A OUTPUT -j REJECT
或者修改策略 还是前者比较好,或者会屏蔽 本地回环地址,还要其他操作开通
[root@node3 ~]# iptables -P INPUT DROP
[root@node3 ~]# iptables -P OUTPUT DROP
1.2 非状态规则添加
80服务器
[root@node3 ~]# iptables -I INPUT -p tcp --dport 80 -j ACCEPT
[root@node3 ~]# iptables -I OUTPUT -p tcp --sport 80 -j ACCEPT
[root@node2 ~]# curl http://192.168.1.202
<html><body><h1>It works!</h1></body></html>
#正式环境不要用,测试环境需要安装yum之类
[root@node3 ~]# iptables -I INPUT -p tcp --sport 80 -j ACCEPT
[root@node3 ~]# iptables -I OUTPUT -p tcp --dport 80 -j ACCEPT
443服务器
[root@node3 ~]# iptables -I INPUT -p tcp --dport 443 -j ACCEPT
[root@node3 ~]# iptables -I OUTPUT -p tcp --sport 443 -j ACCEPT
#正式环境不要用,测试环境需要安装yum之类
[root@node3 ~]# iptables -I INPUT -p tcp --sport 443 -j ACCEPT
[root@node3 ~]# iptables -I OUTPUT -p tcp --dport 443 -j ACCEPT
dns
#域名解析 一般也不用开放 测试环境需要安装yum之类
[root@node3 ~]# iptables -I OUTPUT -p udp --dport 53 -j ACCEPT
[root@node3 ~]# iptables -I INPUT -p udp --sport 53 -j ACCEPT
[root@node3 ~]# ping baidu.com
PING baidu.com (123.125.115.110) 56(84) bytes of data.
64 bytes from 123.125.115.110 (123.125.115.110): icmp_seq=1 ttl=51 time=37.1 ms
#dns服务器
[root@node3 ~]# iptables -I OUTPUT -p tcp --dport 53 -j ACCEPT
[root@node3 ~]# iptables -I INPUT -p tcp --sport 53 -j ACCEPT
ping
#往外ping
[root@node3 ~]# iptables -I INPUT -i ens34 -p icmp --icmp-type 0 -j ACCEPT
[root@node3 ~]# iptables -I OUTPUT -o ens34 -p icmp --icmp-type 8 -j ACCEPT
#被ping
[root@node3 ~]# iptables -I INPUT -i ens34 -p icmp --icmp-type 8 -j ACCEPT
[root@node3 ~]# iptables -I OUTPUT -o ens34 -p icmp --icmp-type 0 -j ACCEPT
ftp
#[root@localhost ~]# modinfo nf_conntrack_ftp
#[root@localhost ~]# lsmod |grep nf_conntrack_ftp
[root@localhost ~]# modprobe nf_conntrack_ftp #装载
#[root@localhost ~]# modprobe -r nf_conntrack_ftp #卸载
[root@node3 ~]# iptables -I INPUT -p tcp -m multiport --dports 21 -m state --state NEW -j ACCEPT
[root@node3 ~]# iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
[root@node3 ~]# iptables -I OUTPUT -m state --state ESTABLISHED -j ACCEPT
ntpdate
#请求
[root@node3 ~]# iptables -I OUTPUT -p udp -m multiport --dports 123,323 -j ACCEPT
[root@node3 ~]# iptables -I INPUT -p udp -m multiport --sports 123,323 -j ACCEPT
samba
[root@node3 ~]# iptables -I INPUT -p udp -m multiport --dports 137,138 -j ACCEPT
[root@node3 ~]# iptables -I OUTPUT -p udp -m multiport --sports 137,138 -j ACCEPT
[root@node3 ~]# iptables -I INPUT -p tcp -m multiport --dports 139,445 -j ACCEPT
[root@node3 ~]# iptables -I OUTPUT -m state --state ESTABLISHED -j ACCEPT
根据ip控制并发
##最大一次5个,每分钟20个,被ping 配合--syn使用
[root@localhost ~]# iptables -I INPUT -p icmp --icmp-type 8 -m limit --limit-burst 5 --limit 20/minute -j ACCEPT
[root@localhost ~]# iptables -I OUTPUT -p icmp --icmp-type 0 -j ACCEPT
2 用状态方式控制
[root@localhost ~]# cat /proc/sys/net/nf_conntrack_max
65536
[root@localhost ~]# vim /etc/sysctl.conf
#net.nf_conntrack_max = 2097152
net.netfilter.nf_conntrack_tcp_timeout_established = 300
net.netfilter.nf_conntrack_max = 1048576 #最大状态连接数
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.ipv4.conf.default.forwarding = 1
[root@localhost ~]# sysctl -p
[root@node3 ~]# iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT
[root@node3 ~]# iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT
#tcp 端口
[root@node3 ~]# iptables -A INPUT -p tcp -m multiport --dports 22,80,443 -m state --state NEW -j ACCEPT
#udp 端口
#[root@node3 ~]# iptables -A INPUT -p dup -m multiport --dports 22,80,443 -m state --state NEW -j ACCEPT
[root@node3 ~]# iptables -A INPUT -j REJECT
[root@node3 ~]# iptables -A OUTPUT -j REJECT
[root@node3 ~]# iptables -vnL
#如果需要解析yum
[root@node3 ~]# iptables -I OUTPUT -p udp -m multiport --dports 53 -m state --state NEW -j ACCEPT
[root@node3 ~]# iptables -I OUTPUT -p tcp -m multiport --dports 80,443 -m state --state NEW -j ACCEPT
目录结构
hostRules.py
#!/root/.virtualenvs/shellenv/bin/python
import os
class generate:
interface = False
ip = False
name = ‘‘
ssh_port = 22
#21 or False
ftp_port = False
# for server response
tcp_in_ports = [80]
udp_in_ports = []
# for server request
out_put_enable = False
tcp_out_ports = []
udp_out_ports = []
ping_in = False
ping_out = False
first_custom_rules = []
middle_custom_rules = []
last_custom_rules = []
EOL=‘\n‘
def __init__(self, config_name):
import yaml
self.name = config_name
file_path = ‘conf/host-{name}.yaml‘.format(name=config_name)
if not os.path.isfile(file_path):
print(‘no config‘)
exit(1)
config = yaml.load(open(file_path))
if config.get(‘ssh_port‘) : self.ssh_port = config.get(‘ssh_port‘)
if config.get(‘ftp_port‘) : self.ftp_port = config.get(‘ftp_port‘)
if config.get(‘tcp_in_ports‘) : self.tcp_in_ports = config.get(‘tcp_in_ports‘)
if config.get(‘udp_in_ports‘) : self.udp_in_ports = config.get(‘udp_in_ports‘)
if config.get(‘out_put_enable‘) : self.out_put_enable = config.get(‘out_put_enable‘)
if config.get(‘tcp_out_ports‘) : self.tcp_out_ports = config.get(‘tcp_out_ports‘)
if config.get(‘udp_out_ports‘) : self.udp_out_ports = config.get(‘udp_out_ports‘)
if config.get(‘ping_in‘) : self.ping_in = config.get(‘ping_in‘)
if config.get(‘ping_out‘) : self.ping_out = config.get(‘ping_out‘)
if config.get(‘ip‘) : self.ip = config.get(‘ip‘)
if config.get(‘interface‘) : self.interface = config.get(‘interface‘)
if config.get(‘first_custom_rules‘) : self.first_custom_rules = config.get(‘first_custom_rules‘)
if config.get(‘middle_custom_rules‘) : self.middle_custom_rules = config.get(‘middle_custom_rules‘)
if config.get(‘last_custom_rules‘) : self.last_custom_rules = config.get(‘last_custom_rules‘)
self.dip = ‘‘
self.sip = ‘‘
if self.ip:
self.dip = ‘ -d ‘+self.ip
self.sip = ‘ -s ‘+self.ip
self.iinterface = ‘‘
self.ointerface = ‘‘
if self.interface:
self.iinterface = ‘ -i ‘+self.interface
self.ointerface = ‘ -o ‘ + self.interface
def start(self):
rules = self.initHostRules()
if self.first_custom_rules:
rules += self.customRules(self.first_custom_rules)
rules += self.established()
if self.ftp_port:
rules += self.enableFtp()
self.tcp_in_ports.append(self.ftp_port)
if self.tcp_in_ports:
rules += self.tcpInRules()
if self.udp_in_ports:
rules += self.udpInRules()
if self.middle_custom_rules:
rules += self.customRules(self.middle_custom_rules)
if self.out_put_enable:
if self.tcp_out_ports:
rules += self.tcpOutRules()
if self.udp_out_ports:
rules += self.udpOutRules()
if self.ping_out:
rules += self.pingOut()
if self.ping_in:
rules += self.pingIn()
if self.last_custom_rules:
rules += self.customRules(self.last_custom_rules)
rules += self.sshRules()
rules += self.rejectRules()
self.write(rules)
pass
def customRules(self,data):
rules = ‘‘
for rule in data:
rules += rule+self.EOL
return rules
def tcpInRules(self):
ports = self.__map_num_2_str(self.tcp_in_ports)
ports = ‘,‘.join(ports)
rules = ‘iptables -A INPUT {ip} {interface} -p tcp -m multiport --dports {ports} -m state --state NEW -j ACCEPT‘.format(ports=ports,ip=self.dip, interface=self.iinterface)+self.EOL+self.EOL
return rules
def udpInRules(self):
ports = self.__map_num_2_str(self.udp_in_ports)
ports = ‘,‘.join(ports)
rules = ‘iptables -A INPUT {ip} {interface} -p udp -m multiport --dports {ports} -m state --state NEW -j ACCEPT‘.format(ports=ports, ip=self.dip, interface=self.iinterface)+self.EOL+self.EOL
return rules
def tcpOutRules(self):
ports = self.__map_num_2_str(self.tcp_out_ports)
ports = ‘,‘.join(ports)
rules = ‘iptables -A OUTPUT {ip} {interface} -p tcp -m multiport --dports {ports} -m state --state NEW -j ACCEPT‘.format(
ports=ports, ip=self.sip, interface=self.ointerface) + self.EOL + self.EOL
return rules
def udpOutRules(self):
ports = self.__map_num_2_str(self.udp_out_ports)
ports = ‘,‘.join(ports)
rules = ‘iptables -A OUTPUT {ip} {interface} -p udp -m multiport --dports {ports} -m state --state NEW -j ACCEPT‘.format(
ports=ports, ip=self.sip, interface=self.ointerface) + self.EOL + self.EOL
return rules
def enableFtp(self):
return ‘modprobe nf_conntrack_ftp‘+ self.EOL
def pingOut(self):
return ‘iptables -A OUTPUT {ip} {interface} -p icmp --icmp-type 0 -j ACCEPT‘.format(ip=self.sip, interface=self.ointerface) + self.EOL
def pingIn(self):
return ‘iptables -A INPUT {ip} {interface} -p icmp --icmp-type 8 -j ACCEPT‘.format(ip=self.dip, interface=self.iinterface) + self.EOL
def established(self):
RELATED=‘‘
if self.ftp_port:
RELATED = ‘,RELATED‘
rules = ‘iptables -A INPUT -m state --state ESTABLISHED{RELATED} -j ACCEPT‘.format(RELATED=RELATED) + self.EOL
rules += ‘iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT‘ + self.EOL + self.EOL
return rules
def initHostRules(self):
rules = ‘iptables -P FORWARD DROP‘+self.EOL
rules += ‘iptables -P INPUT ACCEPT‘+self.EOL
rules += ‘iptables -P OUTPUT ACCEPT‘+self.EOL
rules += ‘iptables -F‘+self.EOL+self.EOL
return rules
def sshRules(self):
if not self.ssh_port:
exit(‘need ssh_port‘)
print(‘ssh port {port}‘.format(port=self.ssh_port))
rules = ‘iptables -A INPUT -p tcp --dport {port} -j ACCEPT‘.format(port=self.ssh_port)+self.EOL
rules += ‘iptables -A OUTPUT -p tcp --sport {port} -j ACCEPT‘.format(port=self.ssh_port)+self.EOL+self.EOL
return rules
def rejectRules(self):
rules = ‘iptables -A INPUT -j REJECT‘+self.EOL
rules += ‘iptables -A OUTPUT -j REJECT‘+self.EOL
return rules
def write(self, data):
data = ‘#!/bin/bash‘+self.EOL+self.EOL + data
with open(‘shell/host-{name}.sh‘.format(name=self.name),mode=‘w‘, encoding=‘utf-8‘) as f:
f.write(data)
def __map_num_2_str(self,data):
return map(lambda x: str(x), data)
if __name__ == ‘__main__‘:
# pydepends = [‘pyyaml‘]
# for i in pydepends:
# os.system(‘/root/.virtualenvs/shellenv/bin/pip install requests -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com ‘+i)
iptables = generate(‘develop‘)
iptables.start()
配置文件在conf下面 host-{name}.yaml 根据各种场景生成rules
ip: 192.168.1.202
interface: ens34
ssh_port: 22
ftp_port: 21
tcp_in_ports: [80, 443,139,445]
udp_in_ports: [80, 443,137,138]
out_put_enable: True
tcp_out_ports: [80, 443]
udp_out_ports: [53,123,323]
ping_in: True
ping_out: True
#单个ip并发
first_custom_rules :
- iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 50 -j REJECT
生成脚本在shell目录下
#!/bin/bash
iptables -P FORWARD DROP
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -F
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 50 -j REJECT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT
modprobe nf_conntrack_ftp
iptables -A INPUT -d 192.168.1.202 -i ens34 -p tcp -m multiport --dports 80,443,139,445,21 -m state --state NEW -j ACCEPT
iptables -A INPUT -d 192.168.1.202 -i ens34 -p udp -m multiport --dports 80,443,137,138 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -s 192.168.1.202 -o ens34 -p tcp -m multiport --dports 80,443 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -s 192.168.1.202 -o ens34 -p udp -m multiport --dports 53,123,323 -m state --state NEW -j ACCEPT
iptables -A OUTPUT -s 192.168.1.202 -o ens34 -p icmp --icmp-type 0 -j ACCEPT
iptables -A INPUT -d 192.168.1.202 -i ens34 -p icmp --icmp-type 8 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT
iptables -A INPUT -j REJECT
iptables -A OUTPUT -j REJECT
实验环境
node1 172.16.86.228
node2 forward
node3 192.168.1.202
在没有规则下,先观察ping
[root@node2 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
[root@node2 ~]# iptables -vnL
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
#node3 访问 node1 http
[root@node3 ~]# ping 172.16.86.228
#如果不通 抓包
[root@node1 ~]# tcpdump -i any -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
17:11:38.783442 IP 192.168.1.202 > 172.16.86.228: ICMP echo request, id 6528, seq 13, length 64 node1收到来自node3的包
17:11:38.783492 IP 172.16.86.228 > 192.168.1.202: ICMP echo reply, id 6528, seq 13, length 64 node1响应给node3
[root@node2 ~]# tcpdump -i any -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
17:12:16.883705 IP 192.168.1.202 > 172.16.86.228: ICMP echo request, id 6528, seq 51, length 64 node3 请求 node1
17:12:16.884212 IP 172.16.86.228 > 192.168.1.202: ICMP echo reply, id 6528, seq 51, length 64 node1响应node3
从这个过程分析得到 无论是哪个网卡接近来的包,出去时候会自动选择一个能到达对面的网卡, 转发过程不会改变原地址和目标地址
添加规则
[root@node2 ~]# iptables -A FORWARD -j REJECT
通用规则
[root@node2 ~]# iptables -I FORWARD -m state --state ESTABLISHED -j ACCEPT
放ping
[root@node2 ~]# iptables -I FORWARD -p icmp --icmp-type 8 -j ACCEPT
tcp
[root@node2 ~]# iptables -I FORWARD -p tcp -m multiport --dports 80,443,139,445 -m state --state NEW -j ACCEPT
udp
[root@node2 ~]# iptables -I FORWARD -p udp -m multiport --dports 53 -m state --state NEW -j ACCEPT
ftp
[root@node2 ~]# modprobe nf_conntrack_ftp #装载
[root@node2 ~]# iptables -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
[root@node2 ~]# iptables -I FORWARD -p tcp -m multiport --dports 21 -m state --state NEW -j ACCEPT
#!/root/.virtualenvs/shellenv/bin/python
import os
class generate:
interface = False
ip = False
name = ‘‘
ssh_port = 22
#21 or False
ftp_port = False
# for server response
tcp_in_ports = [80]
udp_in_ports = []
ping = False
first_custom_rules = []
middle_custom_rules = []
last_custom_rules = []
EOL=‘\n‘
def __init__(self, config_name):
import yaml
self.name = config_name
file_path = ‘conf/forward-{name}.yaml‘.format(name=config_name)
if not os.path.isfile(file_path):
print(‘no config‘)
exit(1)
config = yaml.load(open(file_path))
if config.get(‘ssh_port‘) : self.ssh_port = config.get(‘ssh_port‘)
if config.get(‘ftp_port‘) : self.ftp_port = config.get(‘ftp_port‘)
if config.get(‘tcp_in_ports‘) : self.tcp_in_ports = config.get(‘tcp_in_ports‘)
if config.get(‘udp_in_ports‘) : self.udp_in_ports = config.get(‘udp_in_ports‘)
if config.get(‘out_put_enable‘) : self.out_put_enable = config.get(‘out_put_enable‘)
if config.get(‘tcp_out_ports‘) : self.tcp_out_ports = config.get(‘tcp_out_ports‘)
if config.get(‘udp_out_ports‘) : self.udp_out_ports = config.get(‘udp_out_ports‘)
if config.get(‘ping_in‘) : self.ping_in = config.get(‘ping_in‘)
if config.get(‘ping_out‘) : self.ping_out = config.get(‘ping_out‘)
if config.get(‘first_custom_rules‘) : self.first_custom_rules = config.get(‘first_custom_rules‘)
if config.get(‘middle_custom_rules‘) : self.middle_custom_rules = config.get(‘middle_custom_rules‘)
if config.get(‘last_custom_rules‘) : self.last_custom_rules = config.get(‘last_custom_rules‘)
def start(self):
rules = self.initForwardRules()
if self.first_custom_rules:
rules += self.customRules(self.first_custom_rules)
rules += self.established()
if self.ftp_port:
rules += self.enableFtp()
self.tcp_in_ports.append(self.ftp_port)
if self.tcp_in_ports:
rules += self.tcpInRules()
if self.udp_in_ports:
rules += self.udpInRules()
if self.middle_custom_rules:
rules += self.customRules(self.middle_custom_rules)
if self.ping:
rules += self.doPing()
if self.last_custom_rules:
rules += self.customRules(self.last_custom_rules)
rules += self.sshRules()
rules += self.rejectRules()
self.write(rules)
def customRules(self,data):
rules = ‘‘
for rule in data:
rules += rule+self.EOL
return rules
def tcpInRules(self):
ports = self.__map_num_2_str(self.tcp_in_ports)
ports = ‘,‘.join(ports)
rules = ‘iptables -A FORWARD -p tcp -m multiport --dports {ports} -m state --state NEW -j ACCEPT‘.format(ports=ports)+self.EOL+self.EOL
return rules
def udpInRules(self):
ports = self.__map_num_2_str(self.udp_in_ports)
ports = ‘,‘.join(ports)
rules = ‘iptables -A FORWARD -p udp -m multiport --dports {ports} -m state --state NEW -j ACCEPT‘.format(ports=ports)+self.EOL+self.EOL
return rules
def enableFtp(self):
return ‘modprobe nf_conntrack_ftp‘+ self.EOL
def doPing(self):
return ‘iptables -A FORWARD -p icmp --icmp-type 8 -j ACCEPT‘ + self.EOL
def established(self):
rules = ‘iptables -A FORWARD -m state --state ESTABLISHED -j ACCEPT‘ + self.EOL + self.EOL
return rules
def initForwardRules(self):
rules = ‘iptables -P FORWARD ACCEPT‘+self.EOL
rules += ‘iptables -P INPUT ACCEPT‘+self.EOL
rules += ‘iptables -P OUTPUT ACCEPT‘+self.EOL
rules += ‘iptables -F‘+self.EOL+self.EOL
return rules
def sshRules(self):
if not self.ssh_port:
exit(‘need ssh_port‘)
print(‘ssh port {port}‘.format(port=self.ssh_port))
rules = ‘iptables -A INPUT -p tcp --dport {port} -j ACCEPT‘.format(port=self.ssh_port)+self.EOL
rules += ‘iptables -A OUTPUT -p tcp --sport {port} -j ACCEPT‘.format(port=self.ssh_port)+self.EOL+self.EOL
return rules
def rejectRules(self):
rules = ‘iptables -A INPUT -j REJECT‘+self.EOL
rules += ‘iptables -A OUTPUT -j REJECT‘+self.EOL
return rules
def write(self, data):
data = ‘#!/bin/bash‘+self.EOL+self.EOL + data
with open(‘shell/forward-{name}.sh‘.format(name=self.name),mode=‘w‘, encoding=‘utf-8‘) as f:
f.write(data)
def __map_num_2_str(self,data):
return map(lambda x: str(x), data)
if __name__ == ‘__main__‘:
# pydepends = [‘pyyaml‘]
# for i in pydepends:
# os.system(‘/root/.virtualenvs/shellenv/bin/pip install requests -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com ‘+i)
iptables = generate(‘develop‘)
iptables.start()
配置文件 conf/forward-develop.yaml
ip: False
interface: False
ssh_port: 22
ftp_port: 21
tcp_in_ports: [80, 443,139,445]
udp_in_ports: [80, 443,137,138]
ping: True
#单个ip并发
first_custom_rules :
- iptables -A FORWARD -p tcp --dport 80 -m connlimit --connlimit-above 50 -j REJECT
snat
#在报文离开当前网卡前POSTROUTING转换源地址ip
[root@node2 ~]# iptables -t nat -A POSTROUTING -s 172.16.86.0/24 -j SNAT --to-source 192.168.1.201
dnat
#在报文进入网卡时候在PREROUTING改变目标地址
[root@node2 ~]# iptables -t nat -I PREROUTING -d 192.168.1.201 -p tcp --dport 80 -j DNAT --to-destination 172.16.86.228
[root@node3 ~]# curl http://192.168.1.201
<html><body><h1>It works!</h1></body></html>
#在报文进入网卡时候在PREROUTING改变目标地址和端口
[root@node3 ~]# curl http://192.168.1.201
curl: (7) Failed connect to 192.168.1.201:80; Connection refused
[root@node2 ~]# iptables -t nat -R PREROUTING 1 -d 192.168.1.201 -p tcp --dport 80 -j DNAT --to-destination 172.16.86.228:8080
[root@node3 ~]# curl http://192.168.1.201
<html><body><h1>It works!</h1></body></html>
作用于当前机器,以下例子把80映射到8080端口
[root@node1 ~]# iptables -t nat -A PREROUTING -d 172.16.86.228 -p tcp --dport 80 -j REDIRECT --to-ports 8080
原文地址:http://blog.51cto.com/marvin89/2120399