tcpd即tcp wrapper,TCP Wrapper是一个基于主机的网络访问控制表系统,用于过滤对类Unix系统(如Linux或BSD)的网络访问。其能将主机或子网IP地址、名称及ident查询回复作为筛选标记,实现访问控制。可以用来作为防火墙使用。
关于tcpd的架构可以参阅作者本人的论文:Tcp Wrapper
现在Linux主要使用xinetd来实现
tcpd主要配置文件为:/etc/hosts.deny, /etc/hosts.allow
一般而言,对于一个网络连接请求,linux会首先判断/etc/hosts.allow这个文件,如果远程登录的计算机满足文件/etc/hosts.allow设定的话,就不会去使用/etc/hosts.deny文件了,相反,如果不满足hosts.allow文件设定的规则的话,就会去使用hosts.deny文件了,如果满足hosts.deny的规则,此主机就被限制为不可访问linux服务器,如果也不满足hosts.deny的设定,此主机默认是可以访问 linux服务器的。只有当一个服务由xinetd管理或者支持tcp wrapper功能时才能使用tcpd来做防火墙。
如果想知道一个服务是否支持tcp wrapper功能,可以使用ldd命令查看是否引用了tcp wrapper的库文件: lld $(which sshd)
linux-vdso.so.1 => (0x00007ffff9144000)
libwrap.so.0 => /lib/x86_64-linux-gnu/libwrap.so.0 (0x00007f798ff52000)
libpam.so.0 => /lib/x86_64-linux-gnu/libpam.so.0 (0x00007f798fd44000)
libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f798fb20000)
libck-connector.so.0 => /usr/lib/x86_64-linux-gnu/libck-connector.so.0 (0x00007f798f91c000)
配置文件语法:
<服务 (亦即程序名称,例如sshd)> : : < 动作 >
重点是两个,第一个是找出你想要管理的那个程序的文件名,第二个才是写下来你想要放行或者是抵挡的 IP 或网域呢。
例如:
cat /etc/host.deny
rsync : 127.0.0.100 127.0.0.200 : denycat /etc/host.allow
rsync:192.168.1.0/24 allow
特殊字段:
[root@www ~]# vim /etc/hosts.allow
rsync: 140.116.0.0/255.255.0.0
rsync: 203.71.39.0/255.255.255.0
rsync: 203.71.38.123
rsync: LOCAL
[root@www ~]# vim /etc/hosts.deny
rsync: ALL <==利用 ALL 配置让所有其他来源不可登陆
扩展:
spawn (action)
可以利用后续接的 shell 来进行额外的工作,且具有变量功能,主要的变量内容为: %h (hostname), %a (address), %d (daemon)等等;
twist (action)
立刻以后续的命令进行,且运行完后终止该次联机的要求 (DENY)
例如:
cat /etc/hosts.deny
rsync : ALL: spawn (echo “security notice from host $(/bin/hostname)” ;\echo; /usr/sbin/safe_finger @%h ) | \ /bin/mail -s "%d-%h security" root & \ : twist ( /bin/echo -e "\n\nWARNING connection not allowed.\n\n" )
这个中spawn 到root部分是将侦测的访问者数据送给 root 的邮件信箱,重点在于 safe_finger 的项目,他会侦测到客户端主机的相关信息,然后使用管线命令将这些数据送给 mail 处理, mail 会将该信息以标头为 security 的字样寄给 root 啦!由于 spawn 只是中间的过程,所以还能够有后续的动作!
twist ( /bin/echo -e “\n\nWARNING connection not allowed.\n\n” ): 这个动作会将 Warning 的字样传送到客户端主机的屏幕上! 然后将该联机中断。
相比于tcp wrapper,iptables更通用一些,iptables并不需要软件提供xinted服务的支持,更加灵活,使用范围也更广。
iptables仅仅是用户空间的一个软件,其功能是由内核空间的Netfilter提供,Netfilter是Linux内核中的一个软件框架,用于管理网络数据包。不仅具有网络地址转换(NAT)的功能,也具备数据包内容修改、以及数据包过滤等防火墙功能。 由于Netfilter作用于内核,因此效率相对较高。
当一个网络封包要进入到主机之前,会先经由 NetFilter 进行检查,那就是 iptables 的规则了。 检查通过则接受 (ACCEPT) 进入本机取得资源,如果检查不通过,则可能予以丢弃 (DROP) ! 上图中主要的目的在告知你:『规则是有顺序的』!例如当网络封包进入 Rule 1 的比对时, 如果比对结果符合 Rule 1 ,此时这个网络封包就会进行 Action 1 的动作,而不会理会后续的 Rule 2, Rule 3…. 等规则的分析了。
例:如果你希望禁止192.168.199.143访问本机的80端口,一般你的正确规则可能如下:
但是如果你把1和2颠倒,那么当192.168.199.143试图访问你的80端口时,NetFilter会先匹配第一条规则,允许所有人访问80,然后放行,第二条规则就无效了。
所以一定要安排好规则顺序
链:上面那个例子就是一个链,可以视为有序排列的规则。
表格:iptables里有许多表格,每个表格都定义出自己的默认政策与规则, 且每个表格的用途都不相同,例如下图是Linux下iptables的几个常见表格:
filter (过滤器):主要跟进入 Linux 本机的封包有关。
NAT (地址转换):是 Network Address Translation 的缩写, 这个表格主要在进行来源与目的之 IP 或 port 的转换,与 Linux 本机较无关,主要与 Linux 主机后的局域网络内计算机较有相关。例如将主机A的80端口转发到主机B的2333端口
* PREROUTING:在进行路由判断之前所要进行的规则(DNAT/REDIRECT)
* POSTROUTING:在进行路由判断之后所要进行的规则(SNAT/MASQUERADE)
* OUTPUT:与发送出去的封包有关
mangle (破坏者):这个表格主要是与特殊的封包的路由旗标有关, 早期仅有 PREROUTING 及 OUTPUT 链,不过从 kernel 2.4.18 之后加入了 INPUT 及 FORWARD 链。 由于这个表格与特殊旗标相关性较高,所以像咱们这种单纯的环境当中,较少使用 mangle 这个表格。
用户自定义部分
一个封包经过iptables的处理过程大致如下:
封包进入 Linux 主机使用资源 (路径 A): 在路由判断后确定是向 Linux 主机要求数据的封包,主要就会透过 filter 的 INPUT 链来进行控管;
封包经由 Linux 主机的转递,没有使用主机资源,而是向后端主机流动 (路径 B): 在路由判断之前进行封包表头的修订作业后,发现到封包主要是要透过防火墙而去后端,此时封包就会透过路径 B 来跑动。 也就是说,该封包的目标并非我们的 Linux 本机。主要经过的链是 filter 的 FORWARD 以及 nat 的 POSTROUTING, PREROUTING。
封包由 Linux 本机发送出去 (路径 C): 例如响应客户端的要求,或者是 Linux 本机主动送出的封包,都是透过路径 C 来跑的。先是透过路由判断, 决定了输出的路径后,再透过 filter 的 OUTPUT 链来传送的!当然,最终还是会经过 nat 的 POSTROUTING 链。
注意:不要在远程主机上进行实验,不小心把自己封了就不好玩了。
1.规则查看与清除
查看: iptables [-t tables] [-L] [-nv]
一般而言对于新安装的操作系统,iptables是空的。下面这个例子来自于鸟哥的书:
Chain INPUT (policy ACCEPT) <==针对 INPUT 链,且预设政策为可接受
target prot opt source destination <==说明栏 内容见下方
ACCEPT all – 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED # 只要是封包状态为 RELATED,ESTABLISHED 就予以接受
ACCEPT icmp – 0.0.0.0/0 0.0.0.0/0 # 只要封包协议是 icmp 类型的,就予以放行
ACCEPT all – 0.0.0.0/0 0.0.0.0/0 #无论任何来源 (0.0.0.0/0) 且要去任何目标的封包,不论任何封包格式 (prot 为 all),通通都接受(注意:这一条是针对lo,也就是回环接口的,可以通过iptables-save查看)
ACCEPT tcp – 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 #只要是传给 port 22 的主动式联机 tcp 封包就接受REJECT all – 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited #拒绝全部封包信息
Chain FORWARD (policy ACCEPT) <==针对 FORWARD 链,且预设政策为可接受
target prot opt source destination
REJECT all – 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibitedChain OUTPUT (policy ACCEPT) <==针对 OUTPUT 链,且预设政策为可接受
target prot opt source destination
注意以上信息没有列出iptables的接口信息(例如lo,eth0),如果希望看到更详细的信息可以通过iptables-save
查看。
使用方式相对简单:iptables-save [-t table] #-t指定表格。
上面对应的iptables-save输出如下:
# Generated by iptables-save v1.4.7 on Fri Jul 22 15:51:52 2011
*filter <==星号开头的指的是表格,这里为 filter
:INPUT ACCEPT [0:0] <==冒号开头的指的是链,三条内建的链
:FORWARD ACCEPT [0:0] <==三条内建链的政策都是 ACCEPT 啰!
:OUTPUT ACCEPT [680:100461]
-A INPUT -m state –state RELATED,ESTABLISHED -j ACCEPT <==针对 INPUT 的规则
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT <==这条很重要!针对本机内部接口开放!
-A INPUT -p tcp -m state –state NEW -m tcp –dport 22 -j ACCEPT
-A INPUT -j REJECT –reject-with icmp-host-prohibited
-A FORWARD -j REJECT –reject-with icmp-host-prohibited <==针对 FORWARD 的规则
COMMIT
# Completed on Fri Jul 22 15:51:52 2011
iptables [-t tables] [-FXZ]
由于这三个指令会将本机防火墙的所有规则都清除,但却不会改变预设政策 (policy) , 所以如果你不是在本机下达这三行指令时,很可能你会被自己挡在家门外 (若 INPUT 设定为 DROP 时)!要小心啊!
一般来说,我们在重新定义防火墙的时候,都会先将规则给他清除掉。还记得我们前面谈到的, 防火墙的『规则顺序』是有特殊意义的,所以啰, 当然先清除掉规则,然后一条一条来设定会比较容易一点啦。底下就来谈谈定义预设政策吧!
当你的封包不在你设定的规则之内时,则该封包的通过与否,是以 Policy 的设定为准。可以通过iptables [-t nat] -P [INPUT,OUTPUT,FORWARD] [ACCEPT,DROP]
设定,例如:
[root@www ~]# iptables -P INPUT DROP #INPUT链(从外面进入的包)默认直接丢弃
[root@www ~]# iptables -P OUTPUT ACCEPT #OUTPUT(从本机发出的包)默认放行
[root@www ~]# iptables -P FORWARD ACCEPT #FORWARD(经过本机的包)默认放行
可以通过上面提到的iptables-save查看修改结果。
最基础的过滤: iptables [-AI 链名] [-io 网络接口] [-p 协议] [-s 来源IP/网域] [-d 目标IP/网域] -j [ACCEPT|DROP|REJECT|LOG]
选项与参数:
-AI 链名:针对某的链进行规则的 “插入” 或 “累加”
-A :新增加一条规则,该规则增加在原本规则的最后面。例如原本已经有四条规则,
使用 -A 就可以加上第五条规则!
-I :插入一条规则。如果没有指定此规则的顺序,默认是插入变成第一条规则。
例如原本有四条规则,使用 -I 则该规则变成第一条,而原本四条变成 2~5 号 **推荐使用防止顺序出错**
链 :有 INPUT, OUTPUT, FORWARD 等,此链名称又与 -io 有关,请看底下。
-io 网络接口:设定封包进出的接口规范
-i :封包所进入的那个网络接口,例如 eth0, lo 等接口。需与 INPUT 链配合;
-o :封包所传出的那个网络接口,需与 OUTPUT 链配合;
-p 协定:设定此规则适用于哪种封包格式
主要的封包格式有: tcp, udp, icmp 及 all(全部) 。
-s 来源 IP/网域:设定此规则之封包的来源项目,可指定单纯的 IP 或包括网域,例如:
IP :192.168.0.100
网域:192.168.0.0/24, 192.168.0.0/255.255.255.0 均可。
若规范为『不许』时,则加上 ! 即可,例如:
-s ! 192.168.100.0/24 表示不许 192.168.100.0/24 之封包来源;
-d 目标 IP/网域:同 -s ,只不过这里指的是目标的 IP 或网域。
-j :后面接动作,主要的动作有接受(ACCEPT)、丢弃(DROP)、拒绝(REJECT)及记录(LOG)
例如
iptables -A INPUT -i eth1 -s 192.168.100.10 -j ACCEPT #eth1接收192.168.100.10发来的封包
iptables -A INPUT -i eth1 -s 192.168.100.230 -j DROP #eth1丢弃192.168.100.230发来的封包
iptables -A INPUT -i lo -j ACCEPT #允许本地回环,**不论封包来自何处或去到哪里,只要是来自 lo 这个界面,就予以接受**
PS:注意,与centos不同Debian中并不存在iptables配置文件,通过iptables配置不能自动保存,一般做法是通过iptables-save > /etc/iptables.conf
,然后在/etc/network/if-pre-up.d/添加一个bash脚本,通过iptables-restore重新加载:/sbin/iptables-restore < /etc/iptables.conf
。
针对端口的设定也是最长用到的。 iptables [-AI 链] [-io 网络接口] [-p tcp,udp] <br />[-s 来源IP/网域] [--sport 端口范围] <br />[-d 目标IP/网域] [--dport 端口范围] -j [ACCEPT|DROP|REJECT]
例:
iptables -A INPUT -i eth0 -p tcp --dport 21 -j DROP #丢弃通过eth0的试图连接端口21(一般是ftp)的tcp包
iptables -A INPUT -i eth0 -p tcp -s 192.168.1.0/24 --sport 1024:65534 --dport ssh -j DROP # 只要来自 192.168.1.0/24 的 1024:65535 埠口的封包,且想要连到本机的 ssh(端口号22) port 就直接丢弃
(远程主机千万不要乱封ssh端口,一不小心封错了是很麻烦的)iptables -A INPUT -i eth0 -p tcp --sport 1:1023 --dport 1:1023 --syn -j DROP #将来自任何地方来源 port 1:1023 的主动连接到本机端的 1:1023 tcp请求忽略
mac,是指网卡的mac地址,可以通过指定mac地址来指定规则,这样当使用DHCP服务时,就可通过网卡,而不是IP来指定规则,例如:
iptables -A INPUT -m mac –mac-source aa:bb:cc:dd:ee:ff -j ACCEPT
这条命令会允许局域网内MAC地址为 aa:bb:cc:dd:ee:ff**访问。
state
如果我们的主机是服务端,而客户的端口不停的变,而且不是一台,而是10台的时候,一个个编写规则会很麻烦。 Linux引入netfilter之后,便拥有了状态模块,可以分析出这个想要进入的封包是否为刚刚我发出去的响应。如果是刚刚我发出去的响应,那么就可以予以接受放行。
iptables -A INPUT [-m state] [--state 状态]
-m :一些 iptables 的外挂模块,主要常见的有:
state :状态模块
mac :网络卡硬件地址 (hardware address)
–state :一些封包的状态,主要有:
INVALID :无效的封包,例如数据破损的封包状态
ESTABLISHED:已经联机成功的联机状态;
NEW :想要新建立联机的封包状态;
RELATED :这个最常用!表示这个封包是与我们主机发送出去的封包有关
例: iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT #只要已建立或相关封包就予以通过
iptables -A INPUT -m state --state INVALID -j DROP #只要是不合法封包就丢弃
为了不让攻击者检测到主机存在,通常会drop ICMP type 8 (echo request) ,不接受ping相应。
iptables -A INPUT [-p icmp] [–icmp-type 类型] -j ACCEPT
–icmp-type :后面必须要接 ICMP 的封包类型,也可以使用代号,例如 8 代表 echo request 的意思。
如果采用上面的INPUT默认拒绝策略,可以编写shell脚本:
#!/bin/bash
icmp_type="0 3 4 11 12 14 16 18"
for typeicmp in $icmp_type
do
iptables -A INPUT -i eth0 -p icmp --icmp-type $typeicmp -j ACCEPT
done