Linux之iptables详解及tcpdump

防火墙(Firewall),就是一个隔离工具,工作于主机或者网络的边缘,对于进出本主机或本网络的报文,根据事先定义的检查规则做匹配检测,对于能够被规则匹配到的报文作出相应处理的组件 , 就称之为防火墙,即可称为主机防火墙和网络防火墙 其主机防火墙工作于主机的边缘, 网络防火墙工作于网络的边缘。从防火墙实现的方法又可以划分为软件防火墙和硬件防火墙。其软件防火墙纯软件逻辑实现,而硬件防火墙能实现硬件层实现封包或者解包, 但离不开软件的辅助。目前市场上比较常见的三层, 四层的防火墙,叫网络层的防火墙, 七层的防火墙, 其实就是代理层的网关。

前言

从设计上来讲, 七层防火墙更加安全,但是却带来了效率更低。所以市场的能用方案为两者结合,而又由于我们都需要从防火墙所控制的这个口来访问, 所以防火墙的工作效率就成了用户能够访问数据多少的一个最重要的控制,配置的不好甚至有可能成为流量的瓶颈。

iptables的发展

iptables的前者叫ipfirewall(内核1.X时代),这是一个作者从freeBSD移值过来的, 能够工作在内核当中, 对数据包进行检测的一款简易访问控制工具, 但是ipfirewall工作极其有限(它需要将所有的规则都放进内核中, 这样规则才能够运行起来,而放进内核,这个做法一般是极其困难). 当内核发展到2.X系列的时候, 软件更名为ipchains, 它可以定义多条规则 , 将他们串进来,共同发挥作用,被称之为iptables。可以将规则组成一个列表,实现绝对详细的访问控制功能。
他们都是工作在用户空间中, 定义规则的工具本身并不算是防火墙, 它们定义的规则,可以让在内核空间中的netfilter来读取,并实现让防火墙工作,而放进的地方必须要是特定的位置,必须是tcp/ip协议栈的地方, 而这个tcp/ip协议栈必须经过的地方, 可以实现读取规则的功能称之为netfilter(网络过滤器)。

作者一共在内核空间中选择了5个位置:

  • 从一个网络接口进来, 到另一个网络接口去的
  • 数据包从内核流入用户空间的
  • 数据包从用户空间流出的
  • 进入/离开本机的外网接口
  • 进入/离开本机的内网接口

iptables是工作在用户空间中的, 它可以编写规则,其是一个rules until工具, 通过ipfw(firewall framework)在内核中生成系统规则(其是通过系统调用完成),再由ipchains工具将规则写入内核空间中,并写入netfilter。

iptables的工作机制

从上面知道了作者选择的5个位置, 来作为控制的地方, 其实前三个位置已经基本上能够将路径彻底封锁了, 但是为什么已经在进出的口设置了关卡后还要在内部卡呢 ? 由于数据包尚未进行路由决策,还不知道数据要走向那里, 所以在进出口是没有办法实现数据过滤的. 所以要在内核空间里设置转发的关卡. 进入用户空间的关卡,从用户空间出去的关卡, 那么,既然他们没什么用,那我们为什么还要设置他们呢? 因为我们在做NAT和DNAT的时候,目标地址转换必须在路由之前转换, 所以我们在外网而后内网的接口进行设置关卡。
这五个位置也被称为五个钩子函数(hook functions),也叫五个内置规则链:

  • PREROUTING(路由前)
  • INPUT(数据包流流入入)
  • FORWARD(转发)
  • OUTPUT(数据包流出)
  • POSTROUTING(路由后)

在不同链可实现的不同功能,从功能划分:

  • filter : 过滤,防火墙,做包过滤
  • nat : network address translation,网络地址转换,修改源或目标IP, 也可以改端口
  • mangle : 拆解报文, 做出修改,并且重新封装起来(不修改IP或端口)
  • raw : 关闭nat表上启用的连接追踪功能
    表的优先级,依次顺序为:
  • raw
  • mangel
  • nat
  • filter
    不同的功能应用的链:
  • raw : PREROUTING OUTPUT
  • mangle : PREROUTING INPUT FORWARD OUTPUT POSTROUTING
  • nat : PREROUTING (INPUT) OUTPUT POSTROUTING
  • Centos 7上可以在INPUT上实现nat功能
  • filter : INPUT OUTPUT FORWARD
    从报文流向经过的链
  • 流入 : PREROUTING---->INPUT
  • 流出 : OUTPUT---->POSTROUTING
  • 转发 : PREROUTING--->FORWARD--->POSTROUTING
    路由功能发生的时刻:
    当报文进入本机后, 判断目标主机是谁? 当报文离开本机前, 判断经由那个接口送往下一站?

iptables的链:

  • 内置链: 每个对应一个勾子函数(hook function)
  • 自定义链: 用于对内置链的扩展和补充,可实现更灵活的规则管理机制,被内置链关联,必须由内置链调用才会生效
    iptables添加规则时的考量点:
  • 要实现那种功能,raw mangle filter, 判断添加到那张表上
  • 报文流经过的路径: 判断添加到那个链上
  • 链上的规则次序,即是检查的次序, 因此隐含一定的应用法则:
    • 同类规则(访问同一应用),匹配范围小的放在上面
    • 不同类规则(访问不同应用),匹配到报文频率较大的放在上面
    • 将那此可由一条规则描述的多个规则合并进来
    • 设置默认策略

iptables的规则匹配法则:
规则匹配从上而下依次匹配,如果匹配到了相关的规则,则应用并不检查以下的规则,当所有的规则都未匹配到时,则应用默认策略。

iptables常见用法

1
2
3
4
5
6
7
8
iptables -L -n -v : 查看规则 
iptables -t nat -L -n : 查看nat规则
iptables -F : 清除规则
iptables -t nat -F PREROUTING : 清除nat的PREROUTING规则
iptables -Z : 清除所有的计数器
iptables -Z INPUT 1 : 清除指定规则的计数器
watch -n1 'iptables -L -n -v' : 动态监控iptables的数据信息
tcpdump -i eth1 tcp port 80 and host 172.16.36.61 : 抓取eth1接口tcp协议的80端口并且与172.16.36.61主机相关的报文
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
补充:利用iptables的recent模块来抵御DOS攻击: 22,建立一个列表,保存有所有访问过指定的服务的客户端IP
ssh: 远程连接,
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j DROP
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 300 --hitcount 3 --name SSH -j LOG --log-prefix "SSH Attach: "
iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 300 --hitcount 3 --name SSH -j DROP
1.利用connlimit模块将单IP的并发设置为3;会误杀使用NAT上网的用户,可以根据实际情况增大该值;
2.利用recent和state模块限制单IP在300s内只能与本机建立2个新连接。被限制五分钟后即可恢复访问。
下面对最后两句做一个说明:
1.第二句是记录访问tcp 22端口的新连接,记录名称为SSH
--set 记录数据包的来源IP,如果IP已经存在将更新已经存在的条目
2.第三句是指SSH记录中的IP,300s内发起超过3次连接则拒绝此IP的连接。
--update 是指每次建立连接都更新列表;
--seconds必须与--rcheck或者--update同时使用
--hitcount必须与--rcheck或者--update同时使用
3.iptables的记录:/proc/net/xt_recent/SSH
也可以使用下面的这句记录日志:
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --name SSH --second 300 --hitcount 3 -j LOG --log-prefix "SSH Attack

练习:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
    练习:INPUT和OUTPUT默认策略为DROP;

1、限制本地主机的web服务器在周一不允许访问;新请求的速率不能超过100个每秒;web服务器包含了admin字符串的页面不允许访问;web服务器仅允许响应报文离开本机;

iptables -P OUTPUT DORP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
iptables -A INPUT -d 172.16.36.61 -p tcp --dport 80 -m time --weekdays 2,3,4,5,6,7 -m limit --limit 100/second -j ACCEPT

iptables -A OUTPUT -s 172.16.36.61 -p tcp --sport 80 -m string --algo bm --string "admin" -j DROP (string的关键字过滤,一定要做在output链上, 在回应报文中才应该会有内容)
iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT

[root@Centos6 netfilter]# iptables -L -n
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT tcp -- 172.16.0.0/16 172.16.36.61 tcp dpt:22
ACCEPT tcp -- 0.0.0.0/0 172.16.36.61 tcp dpt:80 TIME on Tue,Wed,Thu,Fri,Sat,Sun limit: avg 100/sec burst 5

Chain FORWARD (policy DROP)
target prot opt source destination

Chain OUTPUT (policy DROP)
target prot opt source destination
DROP tcp -- 172.16.36.61 0.0.0.0/0 tcp spt:80 STRING match "admin" ALGO name bm TO 65535
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED

Chain in_icmp (0 references)
target prot opt source destination

2、在工作时间,即周一到周五的8:30-18:00,开放本机的ftp服务给172.16.0.0网络中的主机访问;数据下载请求的次数每分钟不得超过5个;
~]# modprobe nf_conntrack_ftp (需要使用related的连接状态,需要挂载此模块)
iptables -P OUTPUT DORP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
~]# iptables -A INPUT -s 172.16.0.0/16 -p tcp --dport 21 -m time --weekdays 1,2,3,4,5 --timestart 8:30 --timestop 18:00 -m limit --limit 5/minute -m state --state NEW -j ACCEPT
~]# iptables -A INPUT -s 172.16.0.0/16 -p tcp -m state --state RELATED -j ACCEPT
~]# iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT

3、开放本机的ssh服务给172.16.x.1-172.16.x.100中的主机,x为你的学号,新请求建立的速率一分钟不得超过2个;仅允许响应报文通过其服务端口离开本机;
iptables -P OUTPUT DORP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
~]# iptables -A INPUT -m state --state ESTABLISHED,NEW -j ACCEPT
~]# iptables -A INPUT -d 172.16.36.61 -p tcp --dport 22 -m iprange --src-range 172.16.36.1-172.16.36.100 -m connlimit --connlimit-above 2/minute -j DROP
~]# iptables -A OUTPUT -m state --state ESTABLISHED -j ACCEPT
4、拒绝TCP标志位全部为1及全部为0的报文访问本机;
iptables -P OUTPUT DORP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
5、允许本机ping别的主机;但不开放别的主机ping本机;
~]# iptables -A OUTPUT -p icmp --icmp-type 8 -j ACCEPT
~]# iptables -A INPUT -p icmp --icmp-type 0 -j ACCEPT (如果INPUT上放行了ESTABLISHED,就不需要再放行代码为0的)

练习:判断下述规则的意义:
# iptables -N clean_in
# iptables -A clean_in -d 255.255.255.255 -p icmp -j DROP
# iptables -A clean_in -d 172.16.255.255 -p icmp -j DROP

# iptables -A clean_in -p tcp ! --syn -m state --state NEW -j DROP
# iptables -A clean_in -p tcp --tcp-flags ALL ALL -j DROP
# iptables -A clean_in -p tcp --tcp-flags ALL NONE -j DROP
# iptables -A clean_in -d 172.16.100.7 -j RETURN


# iptables -A INPUT -d 172.16.100.7 -j clean_in

# iptables -A INPUT -i lo -j ACCEPT
# iptables -A OUTPUT -o lo -j ACCEPT(如果在OUTPUT上允许了state为ESTABLISHED的连接, 就不需要再放行,直接可以通过)


等同
# iptables -A INPUT -d 127.0.0.1 -j ACCEPT
# iptables -A OUTPUT -s 127.0.0.1 -j ACCEPT (如果在OUTPUT上允许了state为ESTABLISHED的连接, 就不需要再放行,直接可以通过)


# iptables -A INPUT -i eth0 -m multiport -p tcp --dports 53,113,135,137,139,445 -j DROP
# iptables -A INPUT -i eth0 -m multiport -p udp --dports 53,113,135,137,139,445 -j DROP
# iptables -A INPUT -i eth0 -p udp --dport 1026 -j DROP
# iptables -A INPUT -i eth0 -m multiport -p tcp --dports 1433,4899 -j DROP

# iptables -A INPUT -p icmp -m limit --limit 10/second -j ACCEPT



iptables FORWARD实验:

环境说明:
Centos6_1
eth0
IP : 172.16.36.60/16
gateway:172.16.36.61
Centos6_2
eth0
IP : 172.16.36.61/16
gateway: 172.16.0.1/16(可以不使用网关)
eth1
IP: 192.168.0.1/24

Centos6_3
eth0
IP: 192.168.0.2/24
GATE: 192.168.0.1

说明: 172.16.36.60与61使用桥接网络,处于教室实验网络, 192.168.0.1与0.2处于vmnet2虚拟网络

实验一:
在172.16.36.60服务器安装vsftpd服务, 要求放行ftp服务
Centos 6_2
1 在36.60服务器上安装vsftpd服务, 并确认vsftpd服务监听在21端口
2 设置FORWARD链的默认重力为DROP
iptables -P FORWARD DROP
3 装载模块
~]# modprobe nf_conntrack_ftp
4 FORWARD链策略设置
~]# iptables -A FORWARD -m state --state ESTABLISHED -j ACCEPT #开放两个方向的所有ESTABLISHED连接,放到第一条(因为匹配到的机率最多)
~]# iptables -A FORWARD -d 172.16.36.60 -p tcp --dport 21 -m state --state NEW -j ACCEPT #开放在目标服务器的tcp 21号端口的服务,并且状态为NEW的才放行
~]# iptables -A FORWARD -d 172.16.36.60 -m state --state RELATED -j ACCEPT #将FTP的RELATED连接也放行, 这样客户端才能连接数据端口
5 使用tcpdump工具查看数据包(172.16.36.60端查看)
~]# tcpdump -i eth0 -nn tcp and host 192.168.0.2


6 开放80端口,给192.168./24网络的主机访问:
~]# iptables -R FORWARD 2 -d 172.16.36.60 -p tcp -m multiport --dport 21,80 -m state --state NEW -j ACCEPT
7 测试80端口开放情况(192.168.0.2主机测试)
~]# curl http://172.16.36.60
8 iptbles的查看
[root@Centos6 ~]# iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy DROP)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED
ACCEPT tcp -- 0.0.0.0/0 172.16.36.60 multiport dports 21,80 state NEW
ACCEPT all -- 0.0.0.0/0 172.16.36.60 state RELATED

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

实验二:
在172.16.36.60运行apache服务, 要求内网(192.168.0)网络的主机,访问时, 使用172.16.36.61为源IP地址(SNAT)
1 确认Centos6_2的主机所有规则清空, 默认规则为允许, 以防止干扰规则判断
[root@Centos6 ~]# iptables -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

root@Centos6 ~]# iptables -t nat -L -n
Chain PREROUTING (policy ACCEPT)
target prot opt source destination

Chain POSTROUTING (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination
2 在网络防火墙主机上(172.16.36.61)设置POSTROUTING链的SANT规则
~]# iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j SNAT --to-source 172.16.36.61
3 验证是否源主机为192.168.0.0/24网络的主机访问172.16.36.60主机的web, 源地址更改为172.16.36.61的IP地址
~]# tailf /var/log/httpd/access_log
172.16.36.61 - - [26/Jan/2016:16:27:44 +0800] "GET / HTTP/1.1" 200 25 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.19.1 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"


实验三:
在192.168.0.2的主机安装web服务, 要求外网(172.16.36.60)主机访问时,完成DNAT转换
1 确认FORWARD/POSTROUTING/PREROUTING的链都没有设置规则 , 并且默认规则为ACCEPT
2 在192.168.0.2主机安装web服务,并启动相关服务, 确认并且能正常访问192.168.0.2的服务
3 在网络防火墙主机上(172.16.36.61)设置PREROUTING链的DNAT规则
~]# iptables -t nat -A PREROUTING -d 172.16.36.61 -p tcp --dport 80 -j DNAT --to-destination 192.168.0.2:80
4 在172.16.36.60主机上尝试访问, 并查看192.168.0.2web的访问日志
172.16.36.60 - - [26/Jan/2016:16:27:44 +0800] "GET / HTTP/1.1" 200 25 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.19.1 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
实现三:
在192.168.0.2的主机安装web服务, 要求外网(172.16.36.60)主机访问, 完成PNAT转换
1 确认FORWARD/POSTROUTING/PREROUTING的链都没有设置规则 , 并且默认规则为ACCEPT
2 在192.168.0.2主机安装web服务,并启动相关服务, 确认并且能正常访问192.168.0.2的服务
3 在网络防火墙主机上(172.16.36.61)设置PREROUTING链的DNAT规则
iptables -t nat -A PREROUTING -d 172.16.36.61 -p tcp --dport 80 -j DNAT --to-destination 192.168.0.2:8080