iptables/netfilter从入门到进阶(Blog 17)

博客作业:iptables/netfilter入门到进阶;

防火墙
为了避免用户获取了非授权访问:引入了防火墙机制:将所有的端口堵上;仅开放有限个端口;防火墙是在内核中实现的,因为识别报文的IP和PORT是在TCP/IP协议栈中;

防火墙的分类:
主机防火墙:对单台主机保护
网络防火墙:保护对网络的访问

防火墙的类型:
软件防火墙:通用的CPU,软件级别实现;
硬件防火墙:特定的CPU,在CPU级别实现对报文的拆封和检查;

防火墙在Linux内核中是在报文必经之处有五个勾子函数,统一叫做netfilter。仅需要向这个框架上填充相关的规则就能对来往的报文检查其是否符合。我们是不可能直接操作内核的,所以只能通过用户空间用应用程序,向其传递相关的选项及参数,它就能向内核的框架上填充规则;这个就是Iptables命令;

注意:适用于Linux

iptables命令:
1.0:ipfw
2.0: ipchains
3.0: iptables
4.0:nftables

iptables命令实现的功能不仅仅是防火的功能:
filter: 最基本的功能
nat: 网络地址转换,是IPv4紧缺的最好的解决方案;
manle: 拆封报文;修改报文;
raw:关闭nat的连接追踪功能;

这几个功能即对应了Iptables命令称为的四表;其优先级,依次递增;

内核中的五个勾子函数:
prerouting:路由前
input:进入用户空间
forward:转发
output:从用户空间出来
postrouting:路由后

这几个函数在iptable命令中用函数对应的大写字母表示其链;即五链

路由:决定报文的流向;如果报文的目标IP是本机,即流向INPUT。如果目标IP非本机,就丢弃;但在本机开启了转发功能后,就流向FORWARD链;

在主机中报文的流向:
流入主机,到用户空间:PREROUTING –> INPUT
流出主机:OUPUT –> POSTROUTING
流经主机,到别的主机:PREROUTING –> FORWRAD –> POSTROUTING

iptables实现不同的功能,调用不同的链:
查看链的方法:iptables -t 表名 -L -n
记忆方法:
OUTPUT支持所有的表;
filter: INPUT, OUTPUT, FORWARD
nat: 除了FORWARD的所有链
mangle: 五个链:
raw:命令获取;

报文路由流经主机经由的路径;

iptables,netfileter入门到进阶
使用防火墙即使用iptable命令在不同的链上添加规则;规则匹配时,做出相对的处理,此处理的过程被称为“处理动作”;基于什么匹配叫“匹配条件”;

写规则要领:
1)实现什么功能,即选择表;
2)报文的流向:我提供服务,就先写入站的规则后写出站的规则;我作为客户端,就先写出站的规则后写入站的规则;

iptables命令大概可以抽出一个公式:
iptables -t table COMMAND chain [规则号number] 匹配条件 -j 处理动作
table: raw, mangle, nat, [filter]
省略表时,表示iptables的基本规则:filter。 例如:iptables COMMAND
COMMAND: 增、删、查、改
增:
-A: Append
-A chain
-I: Insert
-I chain
-N: 定义链

删:
-D:删除指定链上的指定规则
-X: 删除链本身:自定义的空的未引用的链才允许删除
-F:清空所有链上的所有规则
-Z:置零链上的数据包;三者都支持
查:
-L sub_command
子命令:-v -n -x –line-number
改:
-R replace

例如:
操作filter表的”所有链所有规则”:-vnxL –line-number
操作filter表的”指定链所有规则”:-vnxL –line-number INPUT
操作filter表的”指定链指定规则”:-vnxL –line-number INPUT 2

匹配条件:rpm -ql iptables 小写模块为匹配条件
基本匹配: 内建功能
[!] -s address[/mask][,…]: 源ip,省略表示所有地址; !表示取反
[!] -d address[/mask][,…]: 目标ip,省略表示所有地址;
[!] -i IFACE: 报文从哪个网卡流入;
[!] -o IFACE: 报文从哪个网卡流出;
扩展匹配:必须加载模块
显式扩展:不用显式指定模块,只要使用-p开头, 就能自动调用对应的模块;
省略-p表示所有协议所有端口;
-p {tcp|udp|icmp} 表示匹配指定协议的所有端口;
-p tcp
[!] {–sport|–dport} port[:port] 匹配tcp协议的指定端口(port)或端口连续的范围(port:port)
[!] [–syn] 匹配syn为1,其它为0的报文;表示仅匹配TCP3次握手的第一次,即建立请求;
-p udp [!] {–sport|–dport} port[:port] 匹配udp协议的指定端口(port)或端口连续的范围(port:port)
-p icmp [!] –icmp-type major[.minor]
major:
8: echo request, 请求;
0: echo reply, 响应;

例如:本地网络允许访问本机的网络 的 22端口:
功能:filter
流向:自己是服务器:INPUT –> OUTPUT
1、关闭防火墙
# systemctl stop firewalld.service
# systemctl mask firewalld.service

2、查看规则并清空规则
# iptables -vnxL –line-number
# iptables -F

3、配置22端口:
~]# iptables -A INPUT -d 172.16.0.67 -s 172.16.0.0/16 -p tcp –dport 22 -j ACCEPT
~]# iptables -A OUTPUT -s 172.16.0.67 -d 172.16.0.0/16 -p tcp –sport 22 -j ACCEPT

4、注意查看是否22号端口是否有数据报文流过:!~!!!
~]# iptables -vnxL –line-number

5、默认策略REJECT
对地址限制:
~]# iptables -A INPUT -d 172.16.0.67 -j REJECT
~]# iptables -A OUTPUT -s 172.16.0.67 -j REJECT
对网卡限制:
~]# ip addr list
~]# iptables -A INPUT -i eno16777736 -j REJECT
~]# iptables -A OUTPUT -o eno16777736 -j REJECT

例如:放行本机的138,137的udp端口;
功能:filter
流向:自己是服务器:INPUT –> OUTPUT
~]# iptables -I INPUT 2 -d 172.16.0.67 -p tcp –dport 137:138 -j ACCEPT
~]# iptables -I OUTPUT 2 -s 172.16.0.67 -p tcp –sport 137:138 -j ACCEPT

例如:只能ping别人,不能被ping?
功能:filter
流向:OUTPUT(8) –> INPUT(0)
~]# iptables -I OUTPUT 2 -s 172.16.0.67 -p icmp –icmp-type 8 -j ACCEPT
~]# iptables -I INPUT 2 -d 172.16.0.67 -p icmp –icmp-type 0 -j ACCEPT

隐式扩展:必须加载模块:-m MODULE_NAME OPTIONS
multiport [!] {–sports|–dports} port[,port|,port:port]… 多个端口以逗号分隔表示离散的端口,以冒号分隔表示连续;

例如:放行本机的22,80,139,445端口给本地网络访问:
功能:filter
流向:自己是服务器:INPUT –> OUTPUT
~]# iptables -R INPUT 1 -d 172.16.0.67 -p tcp -m multiport –dports 22,80,139,445 -j ACCEPT
~]# iptables -R OUTPUT 1 -s 172.16.0.67 -p tcp -m multiport –sports 22,80,139,445 -j ACCEPT

iprange [!] {–src-range|–dst-range} from ipaddress-ipaddress: 匹配地址范围;

例如:开放telnet服务给172.16.0.60-172.16.0.70主机访问?
功能:filter
流向:自己是服务器:INPUT –> OUTPUT
~]# iptables -I INPUT 3 -d 172.16.0.67 -p tcp –dport 23 -m iprange –src-range 172.16.0.60-172.16.0.70 -j ACCEPT
~]# iptables -I OUTPUT 3 -s 172.16.0.67 -p tcp –sport 23 -m iprange –dst-range 172.16.0.60-172.16.0.70 -j ACCEPT

time –timestart hh:mm[:ss] –timestop hh:mm[:ss] [–kerneltz] :匹配时间,centos 7必须加上后者;
[!] {–weekdays|–monthdays} day[,day…] 匹配周几或几日;不能同时使用!
–datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]] 匹配哪年哪月哪日起始,一般不用
–datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]] 匹配哪年哪月哪日结束,一般不用
注意:省略以上三者表示每天的几点到几点;

–kerneltz:使用内核配置的时区而非默认的UTC;

例如:开放telnet服务给172.16.0.60-172.16.0.70主机访问,且仅允许在工作日的9:00-17:00之间被访问?
功能:filter
流向:自己是服务器:INPUT –> OUTPUT
~]# iptables -R INPUT 3 -d 172.16.0.67 -p tcp –dport 23 -m iprange –src-range 172.16.0.60-172.16.0.70 -m time –weekdays 1,2,3,4,5 –timestart 9:00:00 –timestop 17:00:00 –kerneltz -j ACCEPT
~]# iptables -R OUTPUT 3 -s 172.16.0.67 -p tcp –sport 23 -m iprange –dst-range 172.16.0.60-172.16.0.70 -m time –weekdays 1,2,3,4,5 –timestart 9:00:00 –timestop 17:00:00 –kerneltz -j ACCEPT

string –algo {bm|kmp} [!] –string pattern 基于模式匹配字串;仅对明文协议生效。对ssh, https无效,对http, telnet有效;

例如:不允许响应传输hi字串;
功能:filter
流向:响应:OUTPUT
~]# iptables -I OUTPUT -s 172.16.0.67 -m string –algo kmp –string “hi” -j REJECT
上传:请求:INPUT
~]# iptables -I INPUT -d 172.16.0.67 -m string –algo kmp –string “hi” -j REJECT

connlimit –connlimit-{upto|above} n 单个IP的并发数限制;例如:172.16.0.67一次只能启动2个mysql客户端或2个ssh客户端;
upto表示<=;
above表示>
注意:具体如何使用,根据使用场景决定:例如:默认拒绝:<=允许;默认允许:>拒绝;

例如:允许ssh单个IP并发2个;
功能:filter
流向:自己是服务器:INPUT –> OUTPUT
~]# iptables -I INPUT 1 -d 172.16.0.67 -p tcp –dport 22 -m connlimit –connlimit-above 2 -j REJECT
注意:上面已经开启了22号端口,所以用黑名单

limit –limit rate[/second|/minute|/hour|/day] –limit-burst number 对速率限制;
#/second 每秒多少个请求数量;
注意速率限制仅限制单个方向即可;

例如:
1)对Httpd服务限制每秒接收200个请求;
功能:filter
流向:自己是服务器:INPUT –> OUTPUT
即限制入站速率;
~]# iptables -I INPUT -d 172.16.0.67 -p tcp –dport 80 -m limit –limit 200/second –limit-burst 200 -j ACCEPT

2)ping响应默认是每秒1个,限制3秒才一个;即1分钟20个;
注意:只能对别人响应的ping和别人请求的ping做限制;即在INPUT上
~]# iptables -R INPUT 5 -d 172.16.0.67 -p icmp –icmp-type 0 -m limit –limit 20/minute –limit-burst 5 -j ACCEPT

state –state {NEW|ESTABLISHED|RELATED} 表示根据连接追踪表记录情况对来往的报文做检查;
NEW: 表中没有记录,只有第一次请求才是此状态;
ESTABLISHED: 表中有记录,说明第一次检查通过;请求和响应都可以有此状态
RELATED:表中有相关连的连接:例如:第一次检查请求我们的21号通过,第二次检查请求一个大于1024的端口还是原IP,则放行!

连接追踪表:记录于内存中,内存满了,客户端不能请求。对于并发访问量大的服务器,连接追踪表的数量应该调大,且内存要加大!
位置:/proc/net/nf_conntrack
限制记录条目数量:/proc/sys/net/nf_conntrack_max
连接的超时时长:/proc/sys/net/netfilter/*timeout*

使用状态规则思路:
第一次请求为NEW,第二次请求为ESTABLISHED
响应都是为ESTABLISHED;
所以在写状态规则前:iptables -I chain -m state –state ESTABLISHED -j ACCEPT 表示请求和响应都放行ESTABLISHED。
作为服务器提供服务:NEW请求在INPUT
作为客户端去请求服务:NEW请求在OUTPUT
使用被动连接的思路:

VSFTPD工作模式
提供21服务者:第一次是开放21,第二次是开放一个随机端口。RELATED
请求21服务者:第一次是开放随机,第一次是开放随机:所以直接将:iptables -I chain -m state –sate NEW -j ACCEPT

使用状态追踪机制:
不能限速

例如:放行80,22,23,139,445,3306
功能:filter
状态:作为服务器提供服务:NEW请求在INPUT
# iptables -F
非第一次请求:# iptables -A INPUT -m state –state ESTABLISHED -j ACCEPT
第一次请求: # iptables -A INPUT -d 172.16.0.67 -p tcp -m multiport –dports 22,80,23,139,445,3306 -m state –state NEW -j ACCEPT
所有响应: # iptables -A OUTPUT -m state –state ESTABLISHED -j ACCEPT

默认策略:
基于地址
~]# iptables -A INPUT -d 172.16.0.67 -j REJECT
~]# iptables -A OUTPUT -s 172.16.0.67 -j REJECT
基于接口
~]# iptables -A INPUT -i eno16777736 -j REJECT
~]# iptables -A OUTPUT -o eno16777736 -j REJECT
例如:开放udp 137,138 NEW状态
功能:filter
状态:作为服务器提供服务:NEW请求在INPUT
~]# iptables -I INPUT 2 -d 172.16.0.67 -p udp –dport 137:138 -m state –state NEW -j ACCEPT

例如:开放同步时间,123,323端口的udp协议;
功能:filter
状态:作为客户端去请求服务:NEW请求在OUTPUT
~]# iptables -I OUTPUT 2 -s 172.16.0.67 -p udp -m multiport –dports 123,323 -m state –state NEW -j ACCEPT

例如:开放vsftpd服务:
功能:filter
状态:作为服务器提供服务:NEW请求在INPUT;且第一次是开放21,第二次是开放一个随机端口。RELATED
~]# iptables -R INPUT 3 -d 172.16.0.67 -p tcp -m multiport –dports 21:23,80,139,445,3306 -m state –state NEW -j ACCEPT
注意:其它主机不能访问ftp;
~]# modprobe nf_conntrack_ftp
~]# iptables -I INPUT 4 -d 172.16.0.67 -m state –state RELATED -j ACCEPT

处理动作: rpm -ql iptables 大写模块为处理条件
基本动作: 内建功能
ACCEPT:接受
DROP: 丢弃
扩展动作:必须加载模块
REJECT:不接受,还响应他被拒绝;
LOG [–log-level #] [–log-prefix “STRING”] : 默认记录日志于/var/log/message中;

例如:记录telnet服务每次NEW请求于日志中。
~]# iptables -vnL –line-number
3 3 180 ACCEPT tcp — * * 0.0.0.0/0 172.16.0.67 multiport dports 21:23,80,139,445,3306 state NEW
注意23号规则在3号。所以要在其之前添加规则:
~]# iptables -I INPUT 3 -d 172.16.0.67 -p tcp –dport 23 -m state –state NEW -j LOG –log-prefix “access telnet: ”
测试访问:
~]# grep “access telnet: ” /var/log/messages
Dec 10 13:09:17 localhost kernel: access telnet: IN=eno16777736 OUT= MAC=00:0c:29:4f:51:e0:00:26:9e:af:36:6e:08:00 SRC=172.16.0.179 DST=172.16.0.67 LEN=52 TOS=0x00 PREC=0x00 TTL=128 ID=16392 DF PROTO=TCP SPT=55023 DPT=23 WINDOW=8192 RES=0x00 SYN URGP=0

自定义链的名字。表示调用此链,此链的reference+1,即引用数量加1;

例如:仅允许ping所有人:
作为客户端:OUTPUT
请求:icmp 8
~]# iptables -N out_ping_rules
~]# iptables -A out_ping_rules -s 172.16.0.67 -p icmp –icmp-type 8 -m state –state NEW -j ACCEPT
~]# iptables -I OUTPUT 3 -s 172.16.0.67 -j out_ping_rules
添加被ping
~]# iptables -N in_ping_rules
~]# iptables -I in_ping_rules -d 172.16.0.67 -p icmp –icmp-type 8 -m state –state NEW -j ACCEPT
~]# iptables -I INPUT 5 -d 172.16.0.67 -p icmp -j in_ping_rules

RETURN:返回调用者;
例如:允许ping所有,但不允许ping172.16.0.68;
~]# iptables -I out_ping_rules -s 172.16.0.67 -d 172.16.0.68 -p icmp -j RETURN

iptables命令做的操作都在内存中完成,重启服务则会生效,要想永久有效则保存在持久存储的文件中:
保存:iptables-save > /PATH/TO/SOME_RULE_FILE
重载:iptabls-restore < /PATH/FROM/SOME_RULE_FILE

CentOS 6:
保存规则:
service iptables save
保存规则于/etc/sysconfig/iptables文件,覆盖保存;
重载规则:
service iptables restart
默认重载/etc/sysconfig/iptables文件中的规则

配置文件:/etc/sysconfig/iptables-config

例如:将以上所有的规则保存于文件:
~]# iptables-save > /etc/sysconfig/iptables-20171210-v1
~]# iptables-restore < /etc/sysconfig/iptables-20171210-v1

CentOS 7:
(1) 自定义Unit File,进行iptables-restore;

ftp被动连接时,将模块定义在IPTABLES_MODULES=””中 /etc/sysconfig/iptables-config

~]# vim /etc/systemd/system/iptables.service
[Unit]
Description=Iptables Service
Before=network.target
Before=libvirtd.service
Before=NetworkManager.service
[Service]
Type=simple
EnvironmentFile=/etc/sysconfig/iptables-config
ExecStartPre=/bin/bash -c “exec /usr/sbin/modprobe $IPTABLES_MODULES”
ExecStart=/bin/bash -c “exec /usr/sbin/iptables-restore < /etc/sysconfig/iptables-20171213-v2”
ExecStop=/bin/bash -c “exec /usr/sbin/iptables-save > /etc/sysconfig/iptables”
[Install]
WantedBy=multi-user.target
~]# systemctl daemon-reload
~]# systemctl enable vsftpd.service
~]# systemctl enable iptables.service

(2) firewalld服务;
(3) 自定义脚本;

网络防火墙:
(1) 在网关定义,因为非本地网络的通信报文会经由是网关;
(2) filter给的FORWARD; 转发 PREROUTING –> FORWRAD –> POSTROUTING,而过滤只能filter表,所以为FORWARD;

客户端网关防火墙:
不能确定服务端的具体IP
仅能确定客户端的具体IP,通常给一个范围开放;
服务端网关防火墙:
不能确定客户端的具体IP,通常给所有人开放;
仅能确定服务端的具体IP,仅给有限的主机开放;

环境准备:
node1:
eno16777736:192.168.10.2 net1
node2:
eno33554984:192.168.10.254 net1
eno16777736:172.16.0.6 bridge
node3:
eno16777736:172.16.0.67 bridge

前提:
所有防火墙关闭;
node1能ping能,192.168.10.254
node2能ping通, node1,nod3
node3能ping通, 172.16.0.6

报文流向:node1 — node2(eno33554984 — PREROUTING — FORWARD — POSTROUTING — eno16777736) — node3

1、为什么在node1上能ping通node2的172.16.0.6地址;
对于Linux主机来讲:“地址属于内核,与网卡无关”。

2、为什么在node1上不能ping通node3;
根据报文流向可知:node1 –> node3
先在node2的eno33554984抓包分析:~]# tcpdump -i eno33554984 -nn icmp (注意:抓包如此方法)
192.168.10.2 > 172.16.0.67: ICMP echo request,
192.168.10.2 > 172.16.0.67: ICMP echo request,
192.168.10.2 > 172.16.0.67: ICMP echo request,
注意:仅关注这部分;
表示报文已经到达此网卡。
在node2的eno16777736抓包分析:~]# tcpdump -i eno16777736 -nn icmp
没有任何报文。

说明: PREROUTING — FORWARD — POSTROUTING 不通;则是FORWARD没有打开!
[root@localhost ~]# cat /proc/sys/net/ipv4/ip_forward
0

打开FORWARD:~]# sysctl -w net.ipv4.ip_forward=1
还是不通:
先在node2的eno33554984抓包分析:
14:09:26.165715 IP 192.168.10.2 > 172.16.0.67: ICMP echo request, id 12648, seq 314, length 64
14:09:27.180426 IP 192.168.10.2 > 172.16.0.67: ICMP echo request, id 12648, seq 315, length 64

在node2的eno16777736抓包分析:
14:09:47.459987 IP 192.168.10.2 > 172.16.0.67: ICMP echo request, id 12648, seq 335, length 64
14:09:48.474520 IP 192.168.10.2 > 172.16.0.67: ICMP echo request, id 12648, seq 336, length 64

说明:这段路已经通畅!在Node3测试,为什么不回应呢?
在node3的eno16777736抓包分析:
14:11:59.742810 IP 192.168.10.2 > 172.16.0.67: ICMP echo request, id 12648, seq 466, length 64
14:12:00.742701 IP 192.168.10.2 > 172.16.0.67: ICMP echo request, id 12648, seq 467, length 64

说明:没有默认路由:添加路由规则:
~]# route add -net 192.168.10.0/24 gw 172.16.0.6 dev eno16777736

通了!
先在node2的eno33554984抓包分析:
14:15:21.181338 IP 192.168.10.2 > 172.16.0.67: ICMP echo request, (注意:请求)
14:15:21.182078 IP 172.16.0.67 > 192.168.10.2: ICMP echo reply, (注意:响应)

在node2的eno16777736抓包分析:
14:15:39.388731 IP 192.168.10.2 > 172.16.0.67: ICMP echo request, id 12648, seq 683, length 64
14:15:39.389340 IP 172.16.0.67 > 192.168.10.2: ICMP echo reply, id 12648, seq 683, length 64

在node3的eno16777736抓包分析:
14:15:58.565743 IP 192.168.10.2 > 172.16.0.67: ICMP echo request, id 12648, seq 702, length 64
14:15:58.565825 IP 172.16.0.67 > 192.168.10.2: ICMP echo reply, id 12648, seq 702, length 64

通过网关实现:
功能:filter(INPUT, FORWARD, OUTPUT)
网关:报文流向 node1 — node2(eno33554984 — PREROUTING — FORWARD — POSTROUTING — eno16777736) — node3
所以仅能在FORWARD链上进行操作;

将192.网络当作 客户端; 172.67.0.67当作服务端:
此时172和192能相互对ping。

客户端防火墙:
1)仅开放192网络内的所有主机 访问外网的web服务;
1、不知道外网的IP;
2、172.16.0.67仅是外网中浩瀚海洋中的沧海一栗;

FORWARD不影响ssh:
~]# iptables -A FORWARD -j REJECT
此时的效果是node1不能请求node3,且请求过程后在node2上查看REJECT的包有数量;

非状态:
请求:~]# iptables -I FORWARD -s 192.168.10.0/24 -p tcp –dport 80 -j ACCEPT
在Node2上抓包分析:
~]# tcpdump -i eno33554984 -nn tcp port 80
14:29:42.883716 IP 192.168.10.2.40791 > 172.16.0.67.80
14:29:43.889321 IP 192.168.10.2.40791 > 172.16.0.67.80

请注意:没有回来的报文;

~]# tcpdump -i eno16777736 -nn tcp port 80
14:30:41.078966 IP 192.168.10.2.40794 > 172.16.0.67.80
14:30:41.079766 IP 172.16.0.67.80 > 192.168.10.2.40794

请注意:67是回应了的。

说明响应的FORWARD没有打开:

响应: ~]# iptables -I FORWARD 2 -d 192.168.10.0/24 -p tcp –sport 80 -j ACCEPT
在Node2上eno33554984 抓包分析80端口:
14:36:36.966057 IP 172.16.0.67.80 > 192.168.10.2.40796: Flags [S.], seq 787342888, ack 4234809659, win 14480, options [mss 1460,sackOK,TS val 23912515 ecr 3861304,nop,wscale 7], length 0
14:36:36.966367 IP 192.168.10.2.40796 > 172.16.0.67.80: Flags [.], ack 1, win 115, options [nop,nop,TS val 3861313 ecr 23912515], length 0
在Node2上eno16777736 抓包分析80端口:
14:37:41.686423 IP 192.168.10.2.40797 > 172.16.0.67.80: Flags [S], seq 3666394773, win 14600, options [mss 1460,sackOK,TS val 3926032 ecr 0,nop,wscale 7], length 0
14:37:41.687211 IP 172.16.0.67.80 > 192.168.10.2.40797: Flags [S.], seq 3443343486, ack 3666394774, win 14480, options [mss 1460,sackOK,TS val 23977236 ecr 3926032,nop,wscale 7], length 0

在Node3上eno16777736 抓包分析80端口:
14:44:45.809942 IP 192.168.10.2.40798 > 172.16.0.67.80
14:44:45.810071 IP 172.16.0.67.80 > 192.168.10.2.40798

请注意:源地址是192.168.10.2。这样很不安全,就引入了SNAT机制,将源地址转换为网关的接口地址;

SNAT:
~]# iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -p tcp –dport 80 -j SNAT –to-source 172.16.0.6
在Node3上eno16777736 抓包分析80端口:
14:46:41.952947 IP 172.16.0.6.40800 > 172.16.0.67.80
14:46:41.953184 IP 172.16.0.67.80 > 172.16.0.6.40800
注意:源地址是172.16.0.6,此时即使能看见自己的公网地址,但只要网关自己的“主机防火墙”做到位,安全加强就没事了;

状态方式配置:
重置:
~]# iptables -F
~]# iptables -t nat -F
~]# iptables -A FORWARD -j REJECT

状态:
请求有NEW和ESTABLISHED:
响应只能ESTABLISHED;

请求和响应的:~]# iptables -I FORWARD -m state –state ESTABLISHED -j ACCEPT
在Node2上eno33554984 抓包分析80端口:
14:54:08.268057 IP 192.168.10.2.40805 > 172.16.0.67.80: Flags [S], seq 3064237376, win 14600, options [mss 1460,sackOK,TS val 4912614 ecr 0,nop,wscale 7], length 0

在Node2上eno16777736 抓包分析80端口:
不存在;说明请求的FORWARD没有打开!

请求的NEW:~]# iptables -I FORWARD 2 -s 192.168.10.0/24 -p tcp –dport 80 -m state –state NEW -j ACCEPT
在Node2上eno33554984 抓包分析80端口:
14:56:42.044843 IP 192.168.10.2.40807 > 172.16.0.67.80: Flags [S], seq 3951411244, win 14600, options [mss 1460,sackOK,TS val 5066390 ecr 0,nop,wscale 7], length 0
14:56:42.045433 IP 172.16.0.67.80 > 192.168.10.2.40807: Flags [S.], seq 3032164064, ack 3951411245, win 14480, options [mss 1460,sackOK,TS val 25117595 ecr 5066390,nop,wscale 7], length 0
有响应
在Node2上eno16777736 抓包分析80端口:
14:56:42.044916 IP 192.168.10.2.40807 > 172.16.0.67.80: Flags [S], seq 3951411244, win 14600, options [mss 1460,sackOK,TS val 5066390 ecr 0,nop,wscale 7], length 0
14:56:42.045399 IP 172.16.0.67.80 > 192.168.10.2.40807: Flags [S.], seq 3032164064, ack 3951411245, win 14480, options [mss 1460,sackOK,TS val 25117595 ecr 5066390,nop,wscale 7], length 0
在内网主机上已经有数据返回
在Node3上eno16777736 抓包分析80端口:
14:58:04.981834 IP 192.168.10.2.40808 > 172.16.0.67.80: Flags [S], seq 3832854045, win 14600, options [mss 1460,sackOK,TS val 5149313 ecr 0,nop,wscale 7], length 0
14:58:04.982045 IP 172.16.0.67.80 > 192.168.10.2.40808: Flags [S.], seq 4077508747, ack 3832854046, win 14480, options [mss 1460,sackOK,TS val 25200525 ecr 5149313,nop,wscale 7], length 0

请注意:源地址是192.168.10.2。这样很不安全,就引入了SNAT机制,将源地址转换为网关的接口地址;

SNAT:
~]# iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -p tcp –dport 80 -j SNAT –to-source 172.16.0.6
在Node3上eno16777736 抓包分析80端口:
15:00:31.381961 IP 172.16.0.6.40809 > 172.16.0.67.80
15:00:31.382087 IP 172.16.0.67.80 > 172.16.0.6.40809

总结: 如果是192.168.10.0/24不能访问外网:
在网关的通向互联网的接口上抓包分析:
不存在任何报文:说明FORWARD没有打开;
存在回应此请求:说明响应的FORWARD没有打开;

2)开放内网访问外网的所有服务:
重置:
~]# iptables -F
~]# iptables -t nat -F
~]# iptables -A FORWARD -j REJECT
1、非状态:
请求:[root@localhost ~]# iptables -I FORWARD -s 192.168.10.0/24 -j ACCEPT
~]# tcpdump -i eno16777736 -nn tcp port 21
在网关的非本地网络上的网卡上抓包,有响应;但主机上没有结果;说明没有响应的FORWARD规则;

响应:[root@localhost ~]# iptables -I FORWARD 2 -d 192.168.10.0/24 -j ACCEPT
注意: lftp可以使用;web可以使用;
在远端的主机上抓包:
15:12:26.338858 IP 192.168.10.2.48013 > 172.16.0.67.21: Flags [S], seq 3806805776, win 14600, options [mss 1460,sackOK,TS val 6010676 ecr 0,nop,wscale 7], length 0
15:12:26.338978 IP 172.16.0.67.21 > 192.168.10.2.48013: Flags [S.], seq 1173645814, ack 3806805777, win 14480, options [mss 1460,sackOK,TS val 26061882 ecr 6010676,nop,wscale 7], length 0

SNAT:
~]# iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -j SNAT –to-source 172.16.0.6
在远端的主机上抓包:
15:18:55.993893 IP 172.16.0.67.21 > 172.16.0.6.48016
15:18:55.996743 IP 172.16.0.6.48016 > 172.16.0.67.21

在Node2上eno16777736 抓包分析21端口:
15:18:55.986390 IP 172.16.0.67.21 > 172.16.0.6.48016
15:18:55.987850 IP 172.16.0.6.48016 > 172.16.0.67.21
在Node2上eno33554984 抓包分析21端口:
15:18:55.986410 IP 172.16.0.67.21 > 192.168.10.2.48016
15:18:55.987809 IP 192.168.10.2.48016 > 172.16.0.67.21

总结:源地址转换不转换源端口;在远程主机看到的是转换后的结果;

2、状态:
[root@localhost ~]# iptables -F
[root@localhost ~]# iptables -t nat -F
[root@localhost ~]# iptables -A FORWARD -j REJECT
[root@localhost ~]# iptables -I FORWARD -m state –state ESTABLISHED -j ACCEPT
[root@localhost ~]# iptables -I FORWARD -s 192.168.10.0/24 -m state –state NEW -j ACCEPT

SNAT:
~]# iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -j SNAT –to-source 172.16.0.6

将192.网络当作 服务端; 172.67.0.67当作客户端:

服务端防火墙:
不能确定客户端的具体IP
仅能确定服务端的具体IP

报文流向:node3 — node2(eno16777736 — PREROUTING — FORWARD — POSTROUTING — eno33554984) — node1
1)开放内网单个主机 仅提供web服务给外网所有人访问?
[root@localhost ~]# iptables -t nat -F
[root@localhost ~]# iptables -F
[root@localhost ~]# iptables -A FORWARD -j REJECT

非状态配置:
请求:[root@localhost ~]# iptables -A FORWARD -d 192.168.10.2 -p tcp –dport 80 -j ACCEPT
在Node2上eno16777736 抓包分析80端口:
15:38:03.388459 IP 172.16.0.67.50656 > 192.168.10.2.80
15:38:04.394062 IP 172.16.0.67.50656 > 192.168.10.2.80
在本地网卡上只能单向的包,回应的包呢?
在Node2上eno33554984 抓包分析80端口:
15:38:51.051463 IP 172.16.0.67.50657 > 192.168.10.2.80
15:38:51.052237 IP 192.168.10.2.80 > 172.16.0.67.50657
在非本地网卡上可以看到有回应:
在Node1上eno16777736 抓包分析80端口:
15:40:04.033488 IP 172.16.0.67.50658 > 192.168.10.2.80
15:40:04.033568 IP 192.168.10.2.80 > 172.16.0.67.50658

响应:[root@localhost ~]# iptables -I FORWARD 2 -s 192.168.10.2 -p tcp –sport 80 -j ACCEPT
在Node2上eno16777736 抓包分析80端口:
15:43:46.434900 IP 172.16.0.67.50661 > 192.168.10.2.80
15:43:46.437480 IP 192.168.10.2.80 > 172.16.0.67.50661

在Node2上eno33554984 抓包分析80端口:
15:43:46.437274 IP 192.168.10.2.80 > 172.16.0.67.50661
15:43:46.437793 IP 172.16.0.67.50661 > 192.168.10.2.80

在Node1上eno16777736 抓包分析80端口:
15:43:46.441933 IP 192.168.10.2.80 > 172.16.0.67.50661
15:43:46.443837 IP 172.16.0.67.50661 > 192.168.10.2.80

注意:服务端的IP应该被隐藏:这样很不安全:

DNAT:代表服务器接收请求,仅需要去请求网关就可以返回结果;
[root@localhost ~]# iptables -t nat -A PREROUTING -d 172.16.0.6 -p tcp –dport 80 -j DNAT –to-destination 192.168.10.2

请注意:以Node3去请求网关的外网地址:172.16.0.6

在Node2上eno16777736 抓包分析80端口:
15:50:31.559020 IP 172.16.0.67.51361 > 172.16.0.6.80
15:50:31.561719 IP 172.16.0.6.80 > 172.16.0.67.51361
请注意:请求的是网关的80;源: 172.16.0.67.51361 目标:172.16.0.6.80

在Node2上eno33554984 抓包分析80端口:
15:50:31.559047 IP 172.16.0.67.51361 > 192.168.10.2.80
15:50:31.561689 IP 192.168.10.2.80 > 172.16.0.67.51361
请注意:源: 172.16.0.67 目标:192.168.10.2.80

在Node1上eno16777736 抓包分析80端口:
15:50:31.565910 IP 172.16.0.67.51361 > 192.168.10.2.80
15:50:31.566390 IP 192.168.10.2.80 > 172.16.0.67.51361

总结:DNAT转换目标地址时,不指定转换端口,同请求的端口;

状态配置:
请求有NEW和ESTABLISHED
响应只有ESTABLISHED

[root@localhost ~]# iptables -t nat -F
[root@localhost ~]# iptables -F
[root@localhost ~]# iptables -A FORWARD -j REJECT
[root@localhost ~]# iptables -vnL

开放请求和响应的ESTABLISHED:
[root@localhost ~]# iptables -I FORWARD -m state –state ESTABLISHED -j ACCEPT
在eno33554984网卡上不能看到报文:说明请求的FORWARD没有撕开!
开放请求的NEW
[root@localhost ~]# iptables -I FORWARD 2 -d 192.168.10.2 -m state –state NEW -j ACCEPT
在Node2上eno16777736 抓包分析80端口:
16:05:57.834066 IP 172.16.0.67.50671 > 192.168.10.2.80
16:05:57.836114 IP 192.168.10.2.80 > 172.16.0.67.50671

请注意:请求的是网关的80;源: 172.16.0.67.51361 目标:172.16.0.6.80

在Node2上eno33554984 抓包分析80端口:
116:05:57.834090 IP 172.16.0.67.50671 > 192.168.10.2.80
16:05:57.836080 IP 192.168.10.2.80 > 172.16.0.67.50671

请注意:源: 172.16.0.67 目标:192.168.10.2.80

在Node1上eno16777736 抓包分析80端口:
16:05:57.841300 IP 172.16.0.67.50671 > 192.168.10.2.80
16:05:57.841399 IP 192.168.10.2.80 > 172.16.0.67.50671

请注意:客户端怎么可以直接访问真正的服务器呢?

DNAT:网关代理服务器接收请求:
[root@localhost ~]# iptables -t nat -A PREROUTING -d 172.16.0.6 -p tcp –dport 80 -j DNAT –to-destination 192.168.10.2
在Node2上eno16777736 抓包分析80端口:
16:15:37.502189 IP 172.16.0.67.51372 > 172.16.0.6.80
16:15:37.504440 IP 172.16.0.6.80 > 172.16.0.67.51372
请注意:请求的是网关的80;源: 172.16.0.67.51372 目标:172.16.0.6.80

在Node2上eno33554984 抓包分析80端口:
16:15:37.502214 IP 172.16.0.67.51372 > 192.168.10.2.80
16:15:37.504396 IP 192.168.10.2.80 > 172.16.0.67.51372
请注意:源: 172.16.0.67.51372 目标:192.168.10.2.80

在Node1上eno16777736 抓包分析80端口:
16:15:37.502214 IP 172.16.0.67.51372 > 192.168.10.2.80
16:15:37.504396 IP 192.168.10.2.80 > 172.16.0.67.51372

总结:DNAT转换目标地址时,不指定转换端口,同请求的端口;

扩展:
(1) 开放内网单个主机 提供samba, ssh, http, mariadb, https允许被访问。
重置:iptables -F; iptables -t nat -F
[root@localhost ~]# iptables -A FORWARD -j REJECT

非状态:
[root@localhost ~]# iptables -I FORWARD -d 192.168.10.2 -p tcp -m multiport –dports 22,443,80,139,445 -j ACCEPT
[root@localhost ~]# iptables -I FORWARD -d 192.168.10.2 -p udp –dport 137:138 -j ACCEPT
[root@localhost ~]# iptables -I FORWARD 2 -s 192.168.10.2 -p tcp -m multiport –sports 22,443,80,139,445 -j ACCEPT
[root@localhost ~]# iptables -I FORWARD 2 -s 192.168.10.2 -p udp –sport 137:138 -j ACCEPT

DNAT: 代理服务器接收请求
[root@localhost ~]# iptables -t nat -A PREROUTING -d 172.16.0.6 -p tcp -m multiport –dports 22,80,139,443,445 -j DNAT –to-destination 192.168.10.2

注意:在172.16.0.179也将路由指向了172.16.0.6

在Node2上eno33554984 抓包分析80端口:
16:50:45.410044 IP 172.16.0.179.57418 > 192.168.10.2.80: Flags [.], ack 5660, win 254, length 0
16:50:45.510019 IP 172.16.0.179.57419 > 192.168.10.2.80: Flags [.], ack 1366, win 251, length 0

在Node2上eno33554984 抓包分析22端口:
16:52:56.694559 IP 172.16.0.67.50878 > 192.168.10.2.22
16:52:56.697502 IP 192.168.10.2.22 > 172.16.0.67.50878

(2) 状态跟踪机制开放内网单个主机 提供ftp, samba, ssh, http, mariadb, https允许被访问
重置:iptables -F; iptables -t nat -F
[root@localhost ~]# iptables -A FORWARD -j REJECT
请求和响应:[root@localhost ~]# iptables -I FORWARD -m state –state ESTABLISHED -j ACCEPT
在eno33554984上没有回应
请求:[root@localhost ~]# iptables -I FORWARD 2 -d 192.168.10.2 -p tcp -m multiport –dports 21:22,139,445,80,3306,443 -m state –state NEW -j ACCEPT

(3) 开放ftp
[root@localhost ~]# modprobe nf_conntrack_ftp
[root@localhost ~]# iptables -I FORWARD 3 -d 192.168.10.2 -p tcp -m state –state RELATED -j ACCEPT

DNAT:
隐藏服务器地址:通过访问172.16.0.6即可 ;
[root@localhost ~]# iptables -t nat -A PREROUTING -d 172.16.0.6 -p tcp -j DNAT –to-destination 192.168.10.2

注意:使用ftp时,在DNAT中,tcp中不能指明端口,因为被动模式中端口是随机的!

SNAT: 代表客户端去请求服务器,将客户端的源地址修改为网关接口的外网地址;
注意:
1、POSTROUTING做地址转换,FORWARD链配置过滤应该以状态来追踪;因为客户端端口所以放行,响应所有放行,相当于大门敞开;
2、客户端是随机端口,所以不应该固定端口;

DNAT: 代表服务端去响应客户端,将客户端请求的目标地址(即网关自己接口的外网地址)修改为内网的”某个”或”某些”主机的地址或端口;
注意:
1、PREROUTING做地址转换后, FORWARD链配置过滤规则时目标地址是 内网的”某个”或”某些”主机的地址或端口;
2、FORWARD链配置过滤可以状态可以以非状态;

DNAT地址转换:
192.168.10.2监听在8080端口,在外网请求网关的80时,自动映射到8080
~]# iptables -t nat -I PREROUTING -d 172.16.0.6 -p tcp –dport 80 -j DNAT –to-destination 192.168.10.2:8080

REDIRECT: 端口映射:将所以请求80端口定向至8080;例如:本机未监听80服务,打开此功能:别人来请求80时,kernel自己将其映射为8080端口;
注意:
1、PREROUTING将80 端口转换为8080后,主机防火墙FORWARD链配置过滤时的端口是 8080

REDIRECT映射:
172.16.0.6将地址映射到了8080端口;本机192.168.10.2监听在80上;
在2上的网卡上抓包可以看出:
# tcpdump -i eno16777736 -nn tcp port 8080
17:45:51.898055 IP 172.16.0.179.57559 > 192.168.10.2.8080
17:45:51.898749 IP 192.168.10.2.8080 > 172.16.0.179.57559
目标:192.168.10.2.8080
此时在2上配置:# iptables -t nat -A PREROUTING -d 192.168.10.2 -p tcp –dport 8080 -j REDIRECT –to-ports 80

本文来自投稿,不代表Linux运维部落立场,如若转载,请注明出处:http://www.178linux.com/90445

(0)
逆神阳逆神阳
上一篇 2017-12-20
下一篇 2017-12-20

相关推荐

  • 课堂练习及课后作业(0805文本处理工具)

    课堂练习: 1、找出ifconfig命令结果中本机的所有IPv4地址 2、查出分区空间使用率的最大百分比值 3、查出用户UID最大值的用户名、UID及shell类型 4、查出/tmp的权限,以数字方式显示 5、统计当前连接本机的每个远程主机IP的连接数,并按从大到小排序 grep 1、显示/proc/meminfo文件中以大小s开头的行;(要求:使用两种方式…

    Linux干货 2016-08-07
  • tomcat

    编程语言: 硬件级:微码编程,汇编语言 系统级:C,C++,… 应用级:Java, PHP, Python, Ruby, Perl, C#, … 程序:指令+数据 过程式编程:以指令为中心,数据服务于代码; 对象式编程:以数据为中心,指令服务于数据; java Java代码的运行:*.java(source code) –…

    Linux干货 2017-07-03
  • 虽千万人吾往矣

    哈佛有句名言 “当你觉得为时已晚的时候,恰恰是最早的时候”。这句话给了我虽千万人吾往矣的勇气。 之前那份工作懒散 安逸 。当我下定决心从那种环境中走出来的时候还是下了很大的决心。陌生的行业 陌生的环境 陌生的前途。我抱着对这份行业无限的憧憬来到了北京。   作为一个南方人的确有点不适合北方这黄沙漫漫的城市,刚来的一两天不停的打喷嚏,可能这就是北京欢…

    Linux干货 2018-03-26
  • 关于大型网站技术演进的思考(四):存储的瓶颈(4)

    原文出处: 夏天的森林    如果数据库需要进行水平拆分,这其实是一件很开心的事情,因为它代表公司的业务正在迅猛的增长,对于开发人员而言那就是有不尽的项目可以做,虽然会感觉很忙,但是人过的充实,心里也踏实。 数据库水平拆分简单说来就是先将原数据库里的一张表在做垂直拆分出来放置在单独的数据库和单独的表里后更进一步的把本来是一个整体…

    2015-03-11
  • linux命令简单应用

    创建/tmp目录下的:a_c, a_d, b_c, b_d touch /tmp/{a,b}_{c,d} [root@bogon ~]# tree /tmp /tmp |– a_c |– a_d |– b_c |– b_d 创建/tmp/mylinux目录下的: mylinux/ ├── bin ├── boo…

    Linux干货 2016-11-06
  • 马哥教育网络班21期+第四周课程练习

    1、复制/etc/skel目录为/home/tuser1,要求/home/tuser1及其内部文件的属组和其它用户均没有任何访问权限。 ~]# cp -r /etc/skel /home/tuser1; chmod -R gx=— /home/tuser1 [root@mag…

    Linux干货 2016-08-02

评论列表(1条)

  • 马哥教育
    马哥教育 2018-01-07 18:07

    内容上还是蛮多知识点~继续加油~