NAT原理及其他相关工具简介
1 NAT原理
互联网无法直接访问私网地址
#内网访问互联网
中间人的主机装有两块网卡,配置公网和私网地址
SNAT:内网访问互联网时先将请求发送到中间人主机,中间人主机将内网的ip地址和端口号进行相关转换,换成主机上的公网地址,端口号随机但不相同且没人使用,用于区分内网d主机, #替换源地址
PAT:互联网回复报文到中间人上的公网地址,根据发出时的端口号区分转换为内网主机地址,再发送到相关主机上
#互联网访问内网
互联网发送请求到中间人公网地址
DNAT:中间人主机根据请求报文的端口号转换为内网地址并映射到内网相关主机上, #替换目标地址
内网收到请求,回复报文发送到中间人主机,将地址转换为主机上的公网地址并根据转换记录发送回相关地址
#互联网无法直接看到内网的地址,保证一定的安全,但互联网主机无法根据日志等分析客户相关行为,地址转换也需消耗资源
1.1 SNAT搭建
实现内网访问外网地址转换,基于nat表,看不到真实客户端地址,更换源地址
MASQUERADE
基于nat表的target,适用于动态获取的公网IP,如:拨号网络
MASQUERADE选项:
- –to-ports port[-port]
- –random
iptables -t nat -A POSTROUTING -s 10.0.1.0/24 ! –d 10.0.1.0/24 -j MASQUERADE
查找当前上网的公网地址
curl http://ip.sb
curl http://ifconfig.me
1.2 DNAT
外网访问内网,也是基于nat表,能看到真实客户端地址,更换目标地址
iptables -t nat -A PREROUTING -d ExtIP -p tcp|udp --dport PORT -j DNAT --to-destination InterSeverIP[:PORT]
#范例
iptables -t nat -A PREROUTING -d 192.168.10.8 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.7:80
ss 无法看到内核监听的端口,内网端口可与外网端口不一致,
1.3 REDIRECT
基于nat表,通过改变目标IP和端口,将接受的包转发至同一个主机的不同端口,端口重定向
#当用户访问7的主机的90端口时给转换到本机7的80端口
iptables -t nat -A PREROUTING -d 10.0.0.7 -p tcp --dport 90 -j REDIRECT --to-ports 80
1.4 简单SNAT和DNAT搭建
#环境准备
#A仅主机模式
[root@A ~]#hostname -I
192.168.0.6
[root@A ~]#route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0
0.0.0.0 192.168.0.8 0.0.0.0 UG 0 0 0 eth0
#B两块网卡,一个仅主机一个NAT
[root@B ~]#hostname -I
10.0.0.8 192.168.0.8
[root@B ~]#cat /etc/sysctl.conf
net.ipv4.ip_forward=1 #开启ip_forward功能,转发
[root@B ~]#hostname -I
10.0.0.7
[root@B ~]#route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.0.8 0.0.0.0 UG 100 0 0 eth0
10.0.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
#C NAT模式
[root@lC ~]#hostname -I
10.0.0.7
[root@lC ~]#route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.0.8 0.0.0.0 UG 100 0 0 eth0
10.0.0.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
#通过标准模块实现内网访问外网,反之禁止
[root@B ~]#iptables -AFORWARD -j REJECT
[root@B ~]#iptables -IFORWARD -s 10.0.0.0/24 -p tcp --dport 80 -j ACCEPT
[root@B ~]#iptables -IFORWARD -d 10.0.0.0/24 -p tcp --sport 80 -j ACCEPT
[root@B ~]#iptables -I FORWARD -s 10.0.0.0/24 -p icmp --icmp-type 8 -j ACCEPT
[root@B ~]#iptables -I FORWARD -d 10.0.0.0/24 -p icmp --icmp-type 0 -j ACCEPT
[root@B ~]#iptables -vnL --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source
destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 174 14616 ACCEPT icmp -- * * 0.0.0.0/0 10.0.0.0/24 icmptype 0
2 218 18312 ACCEPT icmp -- * * 10.0.0.0/24 0.0.0.0/0 icmptype 8
3 10 1084 ACCEPT tcp -- * * 0.0.0.0/0 10.0.0.0/24 tcp spt:80
4 31 1938 ACCEPT tcp -- * * 10.0.0.0/24 0.0.0.0/0 tcp dpt:80
5 312 25632 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source
destination
#测试
[root@C ~]#ping 192.168.0.6 -c1
PING 192.168.0.6 (192.168.0.6) 56(84) bytes of data.
64 bytes from 192.168.0.6: icmp_seq=1 ttl=63 time=2.20 ms
[root@C ~]#curl 192.168.0.6
internet
[root@A ~]#ping 10.0.0.7 -c1
PING 10.0.0.7 (10.0.0.7) 56(84) bytes of data.
From 192.168.0.8 icmp_seq=1 Destination Port Unreachable
[root@A ~]#curl 10.0.0.7
curl: (7) couldn't connect to host
2 firewall
firewall-config 图形工具: 需安装 firewall-config包
firewall-cmd 命令行工具: firewalld包,默认安装
/etc/firewalld/ 配置文件,一般不建议,如:/etc/firewalld/zones/public.xml
2.1 firewalld-config zone 分类
zone名称 | 默认配置 |
---|---|
trusted | 允许所有流量 |
home | 拒绝除和传出流量相关的,以及ssh,mdsn,ipp-client,samba-client,dhcpv6-client预定义服务之外其它所有传入流量internal 和home相同 |
work | 拒绝除和传出流量相关的,以及ssh,ipp-client,dhcpv6-client预定义服务之外的其它所有传入流量 |
public | 拒绝除和传出流量相关的,以及ssh,dhcpv6-client预定义服务之外的其它所有传入流量,新加的网卡默认属于public zone |
external | 拒绝除和传出流量相关的,以及ssh预定义服务之外的其它所有传入流量,属于external zone的传出ipv4流量的源地址将被伪装为传出网卡的地址。 |
dmz | 拒绝除和传出流量相关的,以及ssh预定义服务之外的其它所有传入流量 |
block | 拒绝除和传出流量相关的所有传入流量 |
drop | 拒绝除和传出流量相关的所有传入流量(甚至不以ICMP错误进行回应) |
预定义服务
ssh、dhcpv6-client、ipp-client、samba-client、mdns
#启动服务firewalld
systemctl start firewalld
2.2 firewall-cmd 命令
--get-zones 列出所有可用区域
--get-default-zone 查询默认区域
--set-default-zone=<ZONE> 设置默认区域
--get-active-zones 列出当前正使用的区域
--add-source=<CIDR>[--zone=<ZONE>] 添加源地址的流量到指定区域,如果无--zone= 选项,使用默认区域
--remove-source=<CIDR> [--zone=<ZONE>] 从指定区域删除源地址的流量,如无--zone= 选项,使用默认区域
--add-interface=<INTERFACE>[--zone=<ZONE>] 添加来自于指定接口的流量到特定区域,如果无--zone= 选项,使用默认区域
--change-interface=<INTERFACE>[--zone=<ZONE>] 改变指定接口至新的区域,如果无--zone=选项,使用默认区域
--add-service=<SERVICE> [--zone=<ZONE>] 允许服务的流量通过,如果无--zone= 选项,使用默认区域
--add-port=<PORT/PROTOCOL>[--zone=<ZONE>] 允许指定端口和协议的流量,如果无--zone= 选项,使用默认区域
--remove-service=<SERVICE> [--zone=<ZONE>] 从区域中删除指定服务,禁止该服务流量,如果无--zone= 选项,使用默认区域
--remove-port=<PORT/PROTOCOL>[--zone=<ZONE>] 从区域中删除指定端口和协议,禁止该端口的流量,如果无--zone= 选项,使用默认区域
--reload 删除当前运行时配置,应用加载永久配置
--list-services 查看开放的服务
--list-ports 查看开放的端口
--list-all [--zone=<ZONE>] 列出指定区域的所有配置信息,包括接口,源地址,端口,服务等,如果无--zone= 选项,使用默认区域
#允许http服务访问
firewall-cmd --add-service=http
#删除允许的服务
firewall-cmd --remove-service=http
#查看目前支持的服务
firewall-cmd --get-services
#查看允许的服务
firewall-cmd --list-services
#查看默认zone
firewall-cmd --get-default-zone
#默认zone设为dmz
firewall-cmd --set-default-zone=dmz
#在internal zone中增加源地址192.168.0.0/24的永久规则, --permanent表示永久保存
firewall-cmd --permanent --zone=internal --add-source=192.168.0.0/24
#在internal zone中增加协议mysql的永久规则
firewall-cmd --permanent --zone=internal --add-service=mysql
#加载新规则以生效
firewall-cmd --reload
3 nft
3.1 nft 命令基本格式
nft 操作符 操作目标 操作内容
1 操作符: 增,删,改,查,清除,插入,创建
表操作:add,delete,list,flush
链操作:add,delete,rename,list,flush,create
规则:add,delete,insert
2 操作目标: 簇,表,链,规则
链类型:filter,route,nat
链钩子:hook
3 操作内容:...
3.2 查看
nft list ruleset # 列出所有规则
nft list tables # 列出所有表
nft list table filter # 列出ip簇的filter表
nft list table inet filter # 列出inet簇的filter表
nft list chain filter INPUT # 列出filter表input链
以上命令后面也可以加 -nn 用于不解析ip地址和端口
加 -a 用于显示 handles
3.3 创建表
#nft默认没有五表五连
#table表示表链接,inet地址簇ipv4和ipv6,表名称test_table
nft add table inet test_table
3.4 创建链
#在test_table表里add chain创建链,链名test_filter_input_chain可自定义,hook input关联到内核里的input钩子函数,默认规则允许
nft add chain inet test_table test_filter_input_chain { type filter hook input priority 0 \; }
3.5 添加规则
#会自动标记端口
nft add rule inet test_table test_filter_input_chain tcp dport http reject
#插入
nft insert rule inet test_table test_filter_input_chain index 0 tcp dport mysql reject
#insert插入 index 0 插入第几条,从0开始记号,代表1
#固定标号handle
nft -a list chain inet test_table test_filter_input_chain #查看handle号,是固定不变的位置标号
nft add rule inet test_table test_filter_input_chain handle 7 tcp dport ftp reject #在handle 7后面添加新规则
#源地址
ip saddr 10.0.0.8 等同iptables -s
删除
#删除表
nft delete table inet test_table
#删除单条规则指明inet簇、表、链、位置handle号
nft delete rule inet test_table test_filter_input_chain handle 8
#清除所有规则
nft flush ruleset
存档规则文件
#更改文件/etc/sysconfig/nftables.conf,去掉注释,可加载该文件里的规则,也可将所需新添加规则写在这里
[root@centos8 ~]#vim /etc/sysconfig/nftables.conf
include "/etc/nftables/main.nft"
#开机启动
systemctl enable --now nftables.service
3.6 通过ntftable来实现暴露本机80/443/ssh服务端口给指定网络访问
[root@rocky ~]#nft add table inet test_table
[root@rocky ~]#nft list table inet test_table
table inet test_table {
}
[root@rocky ~]#nft add chain inet test_table test_chain
[root@rocky ~]#nft list table inet test_table
table inet test_table {
chain test_chain {
}
}
[root@rockyrocky ~]#nft add rule inet test_table test_chain ip saddr 10.0.0.18 tcp --dport 80 accept^C
[root@rocky ~]#nft add rule inet test_table test_chain reject
[root@rocky ~]#nft list table inet test_table
table inet test_table {
chain test_chain {
reject
}
}
[root@rocky ~]#nft insert rule inet test_table test_chain index 0 ip saddr 10.0.0.18 tcp dport 80 accept
[root@rocky ~]#nft list table inet test_table
table inet test_table {
chain test_chain {
ip saddr 10.0.0.18 tcp dport 80 accept
reject
}
}
[root@rocky ~]#nft insert rule inet test_table test_chain index 0 ip saddr 10.0.0.18 tcp dport 443 accept
[root@rocky ~]#nft list table inet test_table
table inet test_table {
chain test_chain {
ip saddr 10.0.0.18 tcp dport 443 accept
ip saddr 10.0.0.18 tcp dport 80 accept
reject
}
}
[root@rocky ~]#nft insert rule inet test_table test_chain index 0 ip saddr 10.0.0.18 tcp dport ssh accept
[root@rocky ~]#nft list table inet test_table
table inet test_table {
chain test_chain {
ip saddr 10.0.0.18 tcp dport 22 accept
ip saddr 10.0.0.18 tcp dport 443 accept
ip saddr 10.0.0.18 tcp dport 80 accept
reject
}
}