Linux提供了一套机制来为用户实现自定义的数据包处理过程。
在linux网络协议中有一组回调函数挂接点,通过这些挂接点挂接的钩子函数可以在linux网络栈处理数据包的过程中对数据进行一些操作,例如过滤、修改、丢弃等。整个挂接点技术叫作Netfilter和Iptables。
Netfilter负责在内核中执行各种挂接的规则,运行在内核模式中。而Iptables是在用户模式下运行的进程,负责协助维护内核中Netfilter的各种规则表。通过二者的配合来实现整个Linux网络协议栈中灵活的数据包处理机制。
Netfilter可以挂接的规则点有5个(链):
挂接点能挂接的规则也分不同的类型(也就是规则表Table),可以在不同类型的Table中加入规则。目前主要支持的Table类型如下:
上述4个Table(规则链)的优先级是RAW最高,FILTER最低。在实际应用中,不同的挂接点需要的规则类型通常不同。例如:在Input的挂接点上明显不需要FILTER过滤规则,因为根据目标地址,已经选择好本机的上层协议栈了,所以无需再挂接FILTER过滤规则。
当Linux协议栈的数据处理运行到挂接点时,会依次调用挂接点上所有的挂钩函数,直到数据包的处理结果是明确地接受或者拒绝。
规则的写法:
iptables [-t table] COMMAND chain CRETIRIA -j ACTION
比如:不允许172.16.0.0/24进行访问
iptables -t filter -A INPUT -s 172.16.0.0/16 -p udp --dport 53 -j DROP
查看定义的详细规则
iptables -L -n -v
每个规则的特性都分为以下几部分。
匹配的参数用于对数据包或者TCP数据连接的状态进行匹配。当有多个条件存在时,它们一起起作用,来达到只针对某部分数据进行修改的目的。常见的匹配参数如下:
一旦数据匹配上,就会执行相应的动作。动作类型既可以是标准的预定义的几个动作,也可以是自定义的模块注册的动作,或者是一个新的规则链,以便更好地组织一组动作。
Iptables命令用于协助用户维护各种规则。查看系统中已有的规则的方法如下:
对于整个TCP协议来讲,它是一个有连接的协议,三次握手中,第一次握手,就叫NEW连接。
第二次握手以后的,ack都为1,这是正常的数据传输,和tcp的第二次第三次握手,叫做已建立的连接(ESTABLISHED)
还有一种状态,比较诡异的,比如:SYN=1 ACK=1 RST=1,对于无法识别的,都称之为INVALID无法识别的。
还有第四种,FTP拥有的特征,每个端口都是独立的,21号和20号端口都是一去一回,他们之间是有关系的,这种关系我们称之为RELATED。
所以我们的状态一共有四种:
清空防火墙策略
iptables -F
凡是目标ip为172.25.254.1的tcp报文都接受
iptables -t filter -A INPUT -d 172.25.254.1 -p tcp -j ACCEPT
凡是从ip为172.25.254.1出去的tcp报文都放行
iptables -t filter -A OUTPUT -s 172.25.254.1 -p tcp -j ACCEPT
iptables -L
删除策略
iptables -L --line-mumbers
iptables -D INPUT 2
iptables -D OUTPUT 2
来自于172.16.0.0/16网段的都允许访问我本机的172.16.100.1的SSH服务。访问本机服务,最好是定义在INPUT链上,出去定义在output链上
将默认策略改成DROP
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
iptables -t filter -A INPUT -s 172.16.0.0/16 -d 172.16.100.1 -p tcp -dport 22 -j ACCEPT
iptables -t filter -A OUTPUT -s 172.16.100.1 -d 172.16.0.0/16 -p tcp -dport 22 -j ACCEPT
进来的只允许ESTABLISHED进来,出去只允许ESTABLISHED出去。
默认规则都使用拒绝。
iptables -L -n –line-number :查看之前的规则位于第几行
iptables -R INPUT 2 -s 172.16.0.0/16 -d 172.16.100.1 -p tcp –dport 22 -m state –state NEW,ESTABLISHED -j ACCEPT
iptables -R OUTPUT 1 -m state --state ESTABLISHED -j ACCEPT
再放行一个80端口
iptables -A INPUT -d 172.16.100.1 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -R INPUT 1 -d 172.16.100.1 -p udp --dport 53 -j ACCEPT
SNAT是指在数据包从网卡发送出去的时候,把数据包中的源地址部分替换为指定的IP,这样,接收方就认为数据包的来源是被替换的那个IP的主机
MASQUERADE是用发送数据的网卡上的IP来替换源IP,因此,对于那些IP不固定的场合,比如拨号网络或者通过dhcp分配IP的情况下,就得用MASQUERADE
DNAT,就是指数据包从网卡发送出去的时候,修改数据包中的目的IP,表现为如果你想访问A,可是因为网关做了DNAT,把所有访问A的数据包的目的IP全部修改为B,那么,你实际上访问的是B
DNAT是在PREROUTING链上来进行的,而SNAT是在数据包发送出去的时候才进行,因此是在POSTROUTING链上进行的
SNAT基于原地址的转换:基于原地址的转换一般用在我们的许多内网用户通过一个外网的口上网的时候,这时我们将我们内网的地址转换为一个外网的IP,就可以实现连接其他外网IP的功能。
将所有192.168.10.0网段的IP在经过的时候全部转换成172.16.100.1这个外网地址:
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -j SNAT -to-source 172.16.100.1
来自本地网络的试图通过网卡访问网络的,都会被统统转换成172.16.100.1这个IP。
外网地址是动态变换的。就要将外网地址换成 MASQUERADE(动态伪装):它可以实现自动寻找到外网地址,而自动将其改为正确的外网地址。所以,我们就需要这样设置:
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -j MASQUERADE
DNAT目标地址转换:
对于目标地址转换,数据流向是从外向内的,外面的是客户端,里面的是服务器端通过目标地址转换,可以让外面的ip通过我们对外的外网ip来访问我们服务器不同的服务器,而我们的服务却放在内网服务器的不同的服务器上。
iptables -t nat -A PREROUTING -d 192.168.10.18 -p tcp --dport 80 -j DNAT --todestination 172.16.100.2
目标地址转换要做在到达网卡之前进行转换,所以要做在PREROUTING这个位置上
现在只有一个IP(10.144.235.10)可以上internet,希望局域网中的三台机器通过SNAT均可上网。
iptables -t nat -A POSTROUTING -s 192.168.80.0/24 -j SNAT --to-source 10.144.235.10
eth0的IP为dhcp获取,IP不固可使用下面转发规则
iptables-t nat -A POSTROUTING -s 192.168.80.0/24 -o eth0 -j MASQUERADE
使用DNAT转发computer1的80端口到10.144.235.10的8088端口
iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 8088 -j DNAT --to-destination 192.168.80.10:80