linux-防火墙2
程序员文章站
2024-02-26 21:02:16
...
--
基于状态的iptables
如果按照tcp/ip来划分连接状态,有11种之多(课后可以自己去读一下相关知识)
但iptables里只有4种状态;ESTABLISHED、NEW、RELATED及INVALID
这两个分类是两个不相干的定义。例如在TCP/IP标准描述下UDP及ICMP数据包是没有连接状态的,但在state模块的描述下,任何数据包都有连接状态。
1、ESTABLISHED
(1)与TCP数据包的关系:首先在防火墙主机上执行SSH Client,并且对网络上的SSH服务器提出服务请求,而这时送出的第一个数据包就是服务请求的数据包,如果这个数据包能够成功的穿越防火墙,那么接下来SSH Server与SSH Client之间的所有SSH数据包的状态都会是ESTABLISHED。
(2)与UDP数据包的关系:假设我们在防火墙主机上用firefox应用程序来浏览网页(通过域名方式),而浏览网页的动作需要DNS服务器的帮助才能完成,因此firefox会送出一个UDP数据包给DNS Server,以请求名称解析服务,如果这个数据包能够成功的穿越防火墙,那么接下来DNS Server与firefox之间的所有数据包的状态都会是ESTABLISHED。
(3)与ICMP数据包的关系:假设我们在防火墙主机ping指令来检测网络上的其他主机时,ping指令所送出的第一个ICMP数据包如果能够成功的穿越防火墙,那么接下来刚才ping的那个主机与防火墙主机之间的所有ICMP数据包的状态都会是ESTABLISHED。
由以上的解释可知,只要第一个数据包能够成功的穿越防火墙,那么之后的所有数据包(包含反向的所有数据包)状态都会是ESTABLISHED。
2、NEW
首先我们知道,NEW与协议无关,其所指的是每一条连接中的第一个数据包,假如我们使用SSH client连接SSH server时,这条连接中的第一个数据包的状态就是NEW。
3、RELATED
RELATED状态的数据包是指被动产生的数据包。而且这个连接是不属于现在任何连接的。RELATED状态的数据包与协议无关,只要回应回来的数据包是因为本机送出一个数据包导致另一个连接的产生,而这一条新连接上的所有数据包都是属于RELATED状态的数据包。
4、INVALID
INVALID状态是指状态不明的数据包,也就是不属于以上三种状态的封包。凡是属于INVALID状态的数据包都视为恶意的数据包,因此所有INVALID状态的数据包都应丢弃掉,匹配INVALID状态的数据包的方法如下:
iptables -A INPUT -p all -m state INVALID -j DROP
我们应将INVALID状态的数据包放在第一条。
|
随机 | 80 web
---------|--》
client | server
《---------|--
随机 | 80
|
client访问server过去
第一个数据包(new状态),如果拒绝,那么后续包都会被拒绝(因为后面来的都会是第一个,都为new状态)
第一个数据包如果允许过去,那么后续包的状态为established
server返回给client
返回的所有包都为established
例1:
有下面两台机
10.1.1.9 10.1.1.10
client server
10.1.1.9是可以ssh访问10.1.1.10,也可以elinks访问10.1.1.10
1,在10.1.1.10上
iptables -P INPUT DROP
iptables -P OUTPUT DROP
这里就把双链都关掉,10.1.1.9任何访问都过不来了
2,
按以前的做法
在10.1.1.10上允许别人ssh进来
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT
在10.1.1.10上允许别人elinks进来
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 80 -j ACCEPT
或者把上面四条合下面两条
iptables -A INPUT -p tcp -m multiport --dport 22,80 -j ACCEPT
iptables -A OUTPUT -p tcp -m multiport --sport 22,80 -j ACCEPT
把上面的两条再换成
iptables -A INPUT -p tcp -m multiport --dport 22,80 -j ACCEPT
iptables -A OUTPUT -p tcp -m state --state established -j ACCEPT
(后面一句可以翻译成tcp协议的连接只要你进得来,你就回得去)
(无论他是用哪个随机端口访问进来的;因为只要能进来,那么后续的包都属于ESTABLISHED状
例2:
有些服务器,可能希望你ping不通他,但是他可以ping通你
方法一:
在服务器上把/proc/sys/net/ipv4/icmp_echo_ignore_all的值改为1
临时修改
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
永久修改
# vim /etc/sysctl.conf --加上下面一句
net.ipv4.icmp_echo_ignore_all = 1
# sysctl -p --使用此命令让其生效
通过iptables的状态来实现
有下面两台机
10.1.1.9 10.1.1.10
实现10.1.1.10这个IP能ping通所有人.但所有人不能ping通10.1.1.10
|
--------------》| ------->
client | server
10.1.1.9 | 10.1.1.10
<-------------| <--------
NEW ESTABLISHED
INPUT 拒绝 允许
OUTPUT 允许 允许
1,在10.1.1.10上
iptables -P INPUT DROP
iptables -P OUTPUT DROP
这里就把双链都关掉,10.1.1.9任何访问都过不来了
2,在10.1.1.10上
iptables -A INPUT -p icmp -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p icmp -m state --state NEW,ESTABLISHED -j ACCEPT
--重点是INPUT那条不能允许NEW状态的;
--注意第二步的第二条(也就是output这条),如果只写了NEW状态,那么10.1.1.10ping所有人,都只能通第一个包;加上ESTABLISHED状态,所有包都能通
例3:
有一个服务器,搭建了http,ftp(主动和被动都要支持,被动端口为3000-3005)两个服务(需要开放给所有人访问),还要开放ssh和ping(但只开放给一个管理ip访问,比如此IP为10.1.1.X),其它任何进来的访问都拒绝
但此服务器要出去访问别的任何服务,自己的防火墙都要允许
需求一个一个的写
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptable -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 21 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 21 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 20 -j ACCEPT
iptables -A INPUT -p tcp --dport 20 -j ACCEPT
iptables -A INPUT -p tcp --dport 3000:3005 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 3000:3005 -j ACCEPT
iptable -A INPUT -p tcp --dport 22 -s 10.1.1.x -j ACCEPT
iptables -A OUTPUT -p tcp --sport 22 -d 10.1.1.x -j ACCEPT
iptable -A INPUT -p icmp -s 10.1.1.x -j ACCEPT
iptables -A OUTPUT -p icmp -d 10.1.1.x -j ACCEPT
iptables -A OUTPUT -p all -m state --state new,established,related -j ACCEPT
iptables -A INPUT -p all -m state --state established,related -j ACCEPT
把上面的综合起来
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptable -A INPUT -p tcp -m multiport --dport 80,21,3000,3001,3002,3003,3004,3005 -j ACCEPT
iptable -A INPUT -p tcp --dport 22 -s 10.1.1.x -j ACCEPT
iptable -A INPUT -p icmp -s 10.1.1.x -j ACCEPT
iptables -A INPUT -p all -m state --state established,related -j ACCEPT
iptables -A OUTPUT -p all -m state --state new,established,related -j ACCEPT
====================================================================================
路由
什么是交换,什么是路由,什么是路由表?
交换是指同网络访问(两台机器连在同一个交换机上,配置同网段的不同ip就可以直接通迅)
路由就是跨网络访问(路径选择)
路由表是记录路由信息的表(可以单路由表,也可以多路由表)
因特网 ---》 物联网(互联网+)
(无数个网络组成,所以从一个网络到另一个网络,中间可能还要经过很多个网络,必需要走路由)
我们现在讨论的是单路由表,你在linux下用route -n查看
# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.2.0 0.0.0.0 255.255.255.0 U 0 0 0 vmnet8
1.1.1.0 0.0.0.0 255.255.255.0 U 0 0 0 vmnet1
172.16.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
0.0.0.0 172.16.254.254 0.0.0.0 UG 0 0 0 eth0
问题1:按上面的路由表来看,如果我ping一个公网IP(如ping 14.215.177.38),应该怎么走?
答案:
我在本机访问一个IP,先看目标ip是否为本地ip,如果是,则直接访问本地;如果不是,则找路由表里是否有你访问的网段,有的话则从这个路由条目后面指定的网卡出去;如果路由表里没有你访问的网段,则会找默认路由(也就是网关);如果网关也没有的话,则会报错网络不可达。
问题2:按上面的路由表来看,如果我ping一个公网IP(如ping 1.1.1.1),会怎么走?
答案:
按上面问题的答案来讲,我ping 1.1.1.1应该不会走网关,而是走本地路由从vmnet1网卡出去(因为路由表里有1.1.1.0/24的路由)。但是1.1.1.1实际应该是一个真正的公网IP.这样其实会影响你访问公网的1.1.1.0/24.所以一般来说,不要在内网网卡上配置公网IP,我这里配置1.1.1.1只是为了方便而已(另一个目的就是为了说明这个问题)
问题3:如何加网关和删除网关,加网关有什么要求?
route add default gw x.x.x.x --临时加网关,马上生效
route del default gw x.x.x.x --临时删网关,马上生效
永久加网关的方法
在网卡配置文件里/etc/sysconfig/network-scripts/ifcfg-eth0
加一句GATEWAY=x.x.x.x
eth0:0
加网关只能加你已经有的路由网段里的一个IP才行(ping不通此IP都可以)
加网关不需要指定子网掩码(因为是已有的一个网段的ip,所以掩码已经确认了)
问题4:一个linux上能有几个有效网关?
准确来说:一个路由表上可以加多个网关,但只有一个生效。但一台linux是可以做多路由表的,一个路由表一个有效网关,多路由表就是多个网关了。
问题5:我一台linux上如果有双物理网卡,请问可不可以两个网卡配置同网段的不同IP呢?
假设我的eth0 10.1.1.5/24
eth1 10.1.1.6/24
如果两个网卡同网段,则会有下面两条路由
10.1.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
10.1.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
它会实现从两张网卡进来的包,却从一张网卡出去,问题就产生了。
也有解决方法(比如多路由表)
实验:
步骤一:
一个虚拟机,开两个网卡,都为桥接网络,配置两个IP,如下
# ifconfig |grep eth -A 1
eth0 Link encap:Ethernet HWaddr 00:0C:29:75:71:E6
inet addr:10.1.1.5 Bcast:10.1.1.255 Mask:255.255.255.0
--
eth1 Link encap:Ethernet HWaddr 00:0C:29:95:B0:42
inet addr:10.1.1.6 Bcast:10.1.1.255 Mask:255.255.255.0
步骤二:
在另一台机器(我这里为宿主机,ip为10.1.1.9),分别ping上面两个ip,得到结果为两个人的MAC都为第一个网卡的
# ip neigh |grep ^10.1.1
10.1.1.5 dev eth0 lladdr 00:0c:29:75:71:e6 REACHABLE
10.1.1.6 dev eth0 lladdr 00:0c:29:75:71:e6 REACHABLE
步骤三:
在虚拟机上ifconfig eth1 down关闭10.1.1.6的网卡,宿主机仍然可以ping通10.1.1.6
结论:在linux上,宿主机ping 10.1.1.6,虚拟机10.1.1.5这个网卡也能收到arp请求,并且会帮10.1.1.6回应(这是由linux默认的内核参数所决定的)
步骤四:
# vim /etc/sysctl.conf --加上
net.ipv4.conf.eth0.arp_ignore = 1
net.ipv4.conf.eth0.arp_announce = 2
net.ipv4.conf.eth1.arp_ignore = 1
net.ipv4.conf.eth1.arp_announce = 2
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
# sysctl -p --用此命令让其生效
最终的效果的是宿主机只能ping通10.1.1.5了,ping不通10.1.1.6了
静态路由
如下图的实验:
IP分配如下(掩码假设全为24位),做实验的话使用iptables -F把所有的防火墙规则清空
1.1.1.0/24网段用vmnet1来模拟
2.2.2.0/24网段用vmnet2来模拟
3.3.3.0/24网段用vmnet3来模拟
4.4.4.0/24网段用vmnet4来模拟
VM1 VM2 VM3 VM4
eth1(vmnet2) eth0(vmnet2) eth1(vmnet4)
2.2.2.2 《--》 2.2.2.3 4.4.4.4
ip_forward ip_forward
eth0 (vmnet1) eth0(vmnet1) eth1(vmnet3) eth0(vmnet3)
1.1.1.1 --》 1.1.1.2 3.3.3.3 《-- 3.3.3.4
sip:1.1.1.1 dip:4.4.4.4
返回
sip:4.4.4.4 dip:1.1.1.1
sip:1.1.1.1 dip:4.4.4.4
返回
sip:4.4.4.4 sip:1.1.1.1
步骤一:
从1.1.1.1 ping 1.1.1.2
在宿主机上ping 1.1.1.2,能通
步骤二:
ping 2.2.2.2 不能通
解决方法:
在vm1上加网关
route add default gw 1.1.1.2
步骤三:
在宿主机加了一个网关指向1.1.1.2的基础上,我再继续在宿主机上ping 2.2.2.3 不能通
解决方法:
在vm3上加网关指向2.2.2.2
route add default gw 2.2.2.2
还要在VM2上打开ip_forward,打开方法有两种
1,# echo 1 > /proc/sys/net/ipv4/ip_forward --马上生效,但重启后就不生效了
2,# vim /etc/sysctl.conf
net.ipv4.ip_forward = 1 --改为1
# sysctl -p --保存后,使用此命令让它永久生效
步骤四:
继续ping 3.3.3.3 不通
解决:再在VM2上route add default gw 2.2.2.3
步骤五:
继续ping 3.3.3.4 不通
解决:在VM3上打开ip_forward
还要在VM4上route add default gw 3.3.3.3
步骤六
继续ping 4.4.4.4 不通
解决:如果在VM3上加一个网关指向3.3.3.4,其实是有问题的,因为VM3上这样就有两个网关了。如果你不使用多路由表的做法,这两个网关只能有一个网关有效。
所以加网关的方式不可行,只能在VM3加路由
route add -net 4.4.4.0 netmask 255.255.255.0 dev eth1
上面终于从1.1.1.1ping到4.4.4.4
--------------------------
那么如果还有5网段,6网段,7网段,甚至更多(类似因特网),全部靠指网关来通迅不现实。实际的做法就是使用路由协议(rip,ospf,bgp等)来做,这就是动态路由了。
如果我把上面的所有网关和ip_forward去掉,然后手动加上路由(也就是说四台机都有四个网段的路由),那么就只能ping通到2.2.2.2,ping2.2.2.3就不通了
linux下可以安装类似zebra这样的软路由软件,可以把linux模拟成一台cisco路由器来进行配置。
======================================================================
======================================================================
准备两台虚拟机和真实机一起三台机做实验(把iptables都先关闭)
A B C
内网(VM1) iptables网关(宿主机) 外网(VM2)
192.168.1.128 --》 192.168.1.1 vmnet1
(vmnet1)
ip_forward
172.16.2.9 eth0 《-- 172.16.2.10
(vmnet0)
--注意:模拟上面的环境时,宿主机可以模拟中间的双网卡网关,但不能模拟内网或外网其中一台(原因是宿主机本来就是与虚拟的所有网段是直通的,你如果把它做为内网,则它会直接连接外网而不会走中间的网关)
--所以两种模拟方法:1,宿主机模拟网关,两台虚拟机分别模拟内外网;2,不要宿主机,三台虚拟机来模拟,中间的双网卡网关使用一台双网关的虚拟机模拟,另两台用单网卡来模拟
把gateway加上路由功能
# echo "1" > /proc/sys/net/ipv4/ip_forward --临时生效
# vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
# sysctl -p --改完后使用此命令,使之修改永久生效
路由功能加了后,网关都指向了gateway这台物理机,那么 两个网段的这两台机就能互相ping通
例一:禁止内网192.168.1.128和外网172.16.2.10互ping
iptables -A FORWARD -p icmp -s 192.168.1.128 -j DROP
或者
iptables -A FORWARD -p icmp -s 172.16.2.10 -j DROP
例二:禁止内网192.168.1.128上外网的172.16.2.10这个网站
iptables -A FORWARD -p tcp --dport 80 -s 192.168.1.128 -d 172.16.2.10 -j DROP
=====================================================================================
问题:这里我们模拟内外网的访问,网关互指,中间网关打开ip_forward,但实际的网络访问环境中,外网客户会把网关指向你公司的网关吗?
张三 李四 王五
内网 iptables网关 外网
(其实就是模拟一个路由器)
192.168.1.128 ----> 192.168.1.1 vmnet1
网关指向
打开ip_forward
172.16.2.9 eth0 172.16.2.10
SIP:192.168.1.128 DIP:172.16.2.10
到达中间iptables网关,需要做SNAT
SIP:172.16.2.9 DIP:172.16.2.10
到达外网服务器,然后返回
SIP:172.16.2.10 DIP:172.16.2.9
回到中间iptables网关,会自动做DNAT
SIP:172.16.2.10 DIP:192.168.1.128
把上图先去掉外网上的网关(因为实际情况下,别人公司的外网服务器不可能把网关指向你),去掉这个网关后,内外网就不能通了,要靠做NAT才能通
张三 李四 王五
发信人:张三 发信人:李四 发信人:王五
收信人:王五 ---> 收信人:王五 -----------> 收信人:李四
|
发信人:王五 |
<----- 收信人:张三 <---------------|
解决方法:在中间网关机器上写规则
实现内网可以上外网的web
iptables -t nat -A POSTROUTING -p tcp --dport 80 -o eth0 -j SNAT --to-source 172.16.2.9
实现内网可以ping外网
iptables -t nat -A POSTROUTING -p icmp -o eth0 -j SNAT --to-source 172.16.2.9
下面这条不写协议,也就表示所有内网上外网的都会做SNAT成172.16.2.9这个IP地址
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 172.16.2.9
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE --这条命令和上条命令实现的效果是一样的,但区别在于MASQUERADE可以动态SNAT成你的公网IP(用于公网IP不固定的情况,比如家用的ADSL拔号上网)
做了SNAT后,并且可以172.16.2.10的/var/log/httpd/access_log里验证得到:在你做NAT之前,靠双网关互指访问网站,它的访问日志里全是你内网的IP。而做了NAT之后,日志里是你公网的IP。
上一篇: Android10(Q)系统源码编译
下一篇: 35