1.Linux 防火墙拓扑图:
2.iptables 机制:
3.iptables -- filter:
a.iptables规则的查看与清除
iptables [-t tables] [-L] [-nv]
参数∶
-t ∶后面接 table ,例如 nat 或 filter ,若省略此项目,则使用预设的 filter
-L ∶列出目前的 table 的规则
-n ∶不进行 IP 与 HOSTNAME 的反查,显示讯息的速度会快很多!
-v ∶列出更多的资讯,包括通过该规则的封包总位元数、相关的网路介面等
iptables [-t tables] [-FXZ]
参数∶
-F ∶清除所有的已订定的规则;
-X ∶杀掉所有使用者 "自订" 的 chain (应该说的是 tables );
-Z ∶将所有的 chain 的计数与流量统计都归零
b.定义预设策略 (policy)
iptables [-t nat] -P [INPUT,OUTPUT,FORWARD] [ACCEPT,DROP]
参数∶
-P ∶定义政策( Policy )。注意,这个 P 为大写!
ACCEPT ∶该封包可接受
DROP ∶该封包直接丢弃,不会让 client 端知道为何被丢弃。
范例∶将本机的 INPUT 设定为 DROP ,其他设定为 ACCEPT
[root@linux ~]#
iptables -P INPUT DROP
[root@linux ~]#
iptables -P OUTPUT ACCEPT
[root@linux ~]#
iptables -P FORWARD ACCEPT
c.IP/netmask 与 I/O的规则设置
iptables [-AI 链] [-io 网卡] [-p 协议] [-s 来源IP/掩码] [-d 目标IP/掩码] -j [ACCEPT|DROP]
参数∶
-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) 及记录 (LOG)
范例∶目标来自 192.168.1.0/24 可接受,但 192.168.1.10 丢弃
[root@linux ~]#
iptables -A INPUT -i eth0 -s 192.168.1.10 -j DROP
[root@linux ~]#
iptables -A INPUT -i eth0 -s 192.168.1.0/24 -j ACCEPT
d.TCP, UDP 的规则设置
iptables [-AI 链] [-io 网卡] [-p tcp,udp] [-s 来源IP/掩码] [--sport 端口范围] [-d 目标IP/掩码] [--dport 端口范围] -j [ACCEPT|DROP]
参数∶
--sport 端口范围∶限制来源的端口号码,端口号码可以是连续的,例如 1024:65535
--dport 端口范围∶限制目标的端口号码。
范例一∶想要连线进入本机 port 21 的封包都抵挡掉∶
[root@linux ~]#
iptables -A INPUT -i eth0 -p tcp --dport 21 -j DROP
范例二∶想连到我这部主机的网芳 (upd port 137,138 tcp port 139,445) 就放行
[root@linux ~]#
iptables -A INPUT -i eth0 -p udp --dport 137:138 -j ACCEPT
[root@linux ~]#
iptables -A INPUT -i eth0 -p tcp --dport 139 -j ACCEPT
[root@linux ~]#
iptables -A INPUT -i eth0 -p tcp --dport 445 -j ACCEPT
范例三:只要来自192.168.1.0/24的 1024:65535端口的封包,只要连接到本机的 ssh port 就予以抵挡:
[root@linux ~]#
iptables -A INPUT -i eth0 -p tcp -s 192.168.1.0/24 --sport 1024:65534 --dport ssh -j DROP
如果你有使用到 --sport 及 --dport 的参数时,就必须指定 udp 或 tcp 的封包格式才行!
范例四:将来自任何地方来源 port 1:1023 的主动连线到本机端的 1:1023 连线丢弃
[root@linux ~]#
iptables -A INPUT -i eth0 -p tcp --sport 1:1023 --dport 1:1023 --syn -j DROP
一般来说,client 端启用的 port 都是大于 1024 以上的端口,而 server 端则是启用小于 1023 以下的端口在监听的。所以我们可以让来自远端的小于 1023 以下的端口资料的主动连线都给他丢弃! 但不适用在 FTP 的主动连线中!
e.ICMP 封包规则设定:
iptables -A INPUT -p icmp --icmp-type 类型 -j ACCEPT
参数∶
--icmp-type ∶后面必须要接 ICMP 的封包类型,也可以使用代号,
例如 8 代表 echo request 的意思。
范例:将主机 ping 的回应功能取消
[root@linux ~]#
iptables -I INPUT -p icmp --icmp-type 8 -j DROP
f.状态模组∶MAC 与 RELATED
iptables -A INPUT -m state --state 状态
参数∶
-m ∶一些 iptables 的模组,主要常见的有∶
state ∶状态模组
mac ∶网路卡硬体位址 (hardware address)
--state ∶一些封包的状态,主要有∶
INVALID ∶无效的封包,例如资料破损的封包状态
ESTABLISHED∶已经连线成功的连线状态;
NEW ∶想要新建立连线的封包状态;
RELATED ∶这个最常用!表示这个封包是与我们主机发送出去的封包有关
范例一∶只要已建立或相关封包就予以通过,只要是不合法封包就丢弃
[root@linux ~]#
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
[root@linux ~]#
iptables -A INPUT -m state --state INVALID -j DROP
范例二∶针对区域网路内的 aa:bb:cc:dd:ee:ff 主机开放其连线
[root@linux ~]#
iptables -A INPUT -m mac --mac-source aa:bb:cc:dd:ee:ff -j ACCEPT
4. NAT 主机的设定
a.什么是 NAT? SNAT? DNAT?
若内部 LAN 有任何一部主机想要传送封包出去时,那么这个封包要如何透过 Linux 主机而传送出去? 他是这样的∶
1.先经过 NAT table 的 PREROUTING 链;
2.经由路由判断确定这个封包是要进入本机与否,若不进入本机,则下一步;
3.再经过 Filter table 的 FORWARD 链;
4.通过 NAT table 的 POSTROUTING 链,最后传送出去。
NAT主机的重点就在于上面流程的第 1,4 步骤,也就是 NAT table 的两条重要的链∶PREROUTING 与 POSTROUTING。那这两条链有什么重要的功能呢?重点在于修改 IP 嘛!但是这两条链修改的 IP 是不一样的! POSTROUTING 在修改来源 IP,PREROUTING 则在修改目标 IP 。 由于修改的 IP 不一样,所以就称为 来源 NAT (Source NAT, SNAT)及目标 NAT (Destination NAT, DNAT)。我们先来谈一谈 IP 分享器功能的 SNAT 吧!
.来源 NAT, SNAT
如上图所示,在用户端 192.168.1.100 这部主机要连线到 http://tw.yahoo.com 去时,他的封包表头会如何变化?
1.用户端所发出的封包表头中,来源会是 192.168.1.100 ,然后传送到 NAT 这部主机;
2.NAT 这部主机的内部介面 (192.168.1.2) 接收到这个封包后,会主动分析表头资料, 因为表头资料显示目的并非 Linux 本机,所以开始经过路由, 将此封包转到可以连接到 Internet 的 Public IP 处;
3.由于 private IP 与 public IP 不能互通,所以 Linux 主机透过 iptables 的 NAT table 内的Postrouting 链将封包表头的来源伪装成为 Linux 的 Public IP ,并且将两个不同来源 (192.168.1.100 及public IP) 的封包对应写入暂存记忆体当中, 然后将此封包传送出去了;
此时 Internet 上面看到这个封包时,都只会知道这个封包来自那个 Public IP 而不知道其实是来自内部啦。 好了,那么如果 Internet 回传封包呢?又会怎么作?
4.在 Internet 上面的主机接到这个封包时,会将回应资料传送给那个 Public IP 的主机;
5.当 Linux NAT 主机收到来自 Internet 的回应封包后,会分析该封包的序号,并比对刚刚记录到记忆体当中的资料,由于发现该封包为后端主机之前传送出去的,因此在 NAT Prerouting 链中,会将目标 IP 修改成为后端主机,亦即那部192.168.1.100,然后发现目标已经不是本机 (public IP), 所以开始透过路由分析封包流向;
6.封包会传送到 192.168.1.2 这个内部介面,然后再传送到最终目标 192.168.1.100 机器上去!
.目标 NAT, DNAT
假设我的内部主机 192.168.1.210 启动了 WWW 服务,这个服务的 port 开启在 port 80 , 那么Internet 上面的主机 (61.xx.xx.xx) 要如何连接到我的内部伺服器呢?当然啦, 还是得要透过 Linux NAT主机嘛!所以这部 Internet 上面的机器必须要连接到我们的 NAT 的 public IP 才行。
1.外部主机想要连接到目的端的 WWW 服务,则必须要连接到我们的 NAT 主机上头;
2.我们的 NAT 主机已经设定好要分析出 port 80 的封包,所以当 NAT 主机接到这个封包后, 会将目标 IP 由 public IP 改成 192.168.1.210 ,且将该封包相关资讯记录下来,等待内部伺服器的回应;
3.上述的封包在经过路由后,来到 private 介面处,然后透过内部的 LAN 传送到 192.168.1.210 上头!
4.192.186.1.210 会回应资料给 61.xx.xx.xx ,这个回应当然会传送到 192.168.1.2 上头去;
5.经过路由判断后,来到 NAT Postrouting 的链,然后透过刚刚第二步骤的记录,将来源 IP 由 192.168.1.210 改为 public IP 后,就可以传送出去了! (类似图十的状态!)。
其实整个步骤几乎就等于 SNAT 的反向传送!
b.NAT主机:IP分享功能
由刚刚的介绍我们知道,这个IP分享器的功能其实就是SNAT啦!作用就只是在iptables内的NAT表格当中,那个路由后的POSTROUTING链进行IP的伪装就是了。另外,NAT主机必须要有一个public IP接口,以及一个内部LAN连接的privateIP接口才行。
同样的,我的假设是这样的∶
.外部介面使用 eth1 ,这个介面具有 public IP;
.内部介面使用 eth0 ,假设这个 IP 为 192.168.1.2;
要使linux具有路由功能:(1)允许内网网段地址的传入;(2)开启主机的router功能.
iptables -A INPUT -i 192.168.1.0/24 -j ACCEPT
# 这一行在让 NAT 主机可接受来自内部 LAN 的封包
echo "1" > /proc/sys/net/ipv4/ip_forward
# 上头这一行则是在让你的 Linux 具有 router 的能力
iptables -t nat -A POSTROUTING -s 内网地址/掩码 -o eth1 -j MASQUERADE
事实上,除了 IP 伪装 (MASQUERADE) 之外,我们还可以直接指定修改 IP 封包表头的来源 IP 呢! 举例来说,如下面这个例子∶
范例一:将要由 eth1 传送出去的封包,封包来源改为 192.168.200.250
[root@linux ~]#
iptables -t nat -A POSTROUTING -o eth1 -j SNAT --to 192.168.200.250
范例二:同上,但封包来源为 192.168.200.210~220
[root@linux ~]#
iptables -t nat -A POSTROUTING -o eth1 -j SNAT --to 192.168.200.210-192.168.200.210
c.防火墙映射:DNAT设定
范例一:将连接到 eth1 介面的 port 80 传导到内部的192.168.1.210
[root@linux ~]#
iptables -t nat -A PREROUTING -p tcp -i eth1 --dport 80 -j DNAT --to 192.168.1.210:80
范例二:将要求与 80 连线的封包转递到 8080 这个 port
[root@linux ~]#
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
# 这玩意最容易在您使用了非正规的 port 来进行某些 well known 的协定,
# 例如使用 8080 这个 port 来启动 WWW ,但是别人都以 port 80 来连线,
# 所以,您就可以使用上面的方式来将对方对您主机的连线传递到 8080!
5.iptables防火墙的保存、恢复与测试
[root@linux ~]#
iptables-save > filename
[root@linux ~]#
iptables-restore < filename
RHEL,CentOS,Fedora 当中,如果你将那个 filename 档案存成『 /etc/sysconfig/iptables』,并且利用 chkconfig 将 iptables 在开机时预设启动的话,那么一开机系统就会主动的帮你把防火墙的规则给载入了!
6.IPv4 的核心管理功能∶
/proc/sys/net/ipv4/*
[root@linux ~]#
echo "1" > /proc/sys/net/ipv4/tcp_syncookies
透过此一机制可以大大的降低无效的 SYN 等待埠口,而避免 SYN Flooding 的 DoS 攻击说!
[root@linux ~]#
echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
核心取消 ping 回应的设定值有两个,分别是∶/proc/sys/net/ipv4 内的icmp_echo_ignore_broadcasts (仅有 ping broadcast 位址时才取消 ping 的回应) 及icmp_echo_ignore_all (全部的 ping 都不回应)。
如果想修改默认内核设定,可在/etc/sysctl.conf 里添加如下两句:
net.ipv4.tcp_syncookies = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
/proc/sys/net/ipv4/conf/网路介面/*
咱们的核心还可以针对不同的网路介面进行不一样的参数设定喔!网路介面的相关设定放置在 /proc/sys/net/ipv4/conf/当中,每个介面都以介面代号做为其代表,例如 eth0 介面的相关设定资料在 /proc/sys/net/ipv4/conf/eth0/内。那么网路介面的设定资料有哪些比较需要注意的呢? 大概有底下这几个∶
rp_filter∶称为逆向路径过滤 (Reverse Path Filtering),可以藉由分析网路介面的路由资讯配合封包的来源位址,来分析该封包是否为合理。举例来说,你有两张网卡,eth0 为192.168.10.100/24 ,eth1 为 public IP 。那么当有一个封包自称来自 eth1 ,但是其 IP 来源为192.168.10.200 , 那这个封包就不合理,应予以丢弃。这个设定值建议可以启动的。
log_martians∶这个设定资料可以用来启动记录不合法的 IP 来源, 举例来说,包括来源为 0.0.0.0、127.x.x.x、及 Class E 的 IP来源,因为这些来源的 IP 不应该应用于 Internet 啊。 记录的资料预设放置到核心放置的登录档 /var/log/messages。
accept_source_route∶或许某些路由器会启动这个设定值, 不过目前的设备很少使用到这种来源路由,你可以取消这个设定值。
accept_redirects∶当你在同一个实体网域内架设一部路由器, 但这个实体网域有两个 IP 网域,例如 192.168.0.0/24,192.168.1.0/24。此时你的 192.168.0.100 想要向 192.168.1.100 传送讯息时,路由器可能会传送一个ICMP redirect 封包告知 192.168.0.100 直接传送资料给 192.168.1.100 即可,而不需透过路由器。因为192.168.0.100 与 192.168.1.100确实是在同一个实体线路上 (两者可以直接互通),所以路由器会告知来源 IP使用最短路径去传递资料。但那两部主机在不同的 IP 段,却是无法实际传递讯息的!这个设定也可能会产生一些轻微的安全风险,所以建议关闭他。
send_redirects∶与上一个类似,只是此值为发送一个 ICMP redirect 封包。 同样建议关闭。(事实上,鸟哥在某补教中心教同学架设路由器时,就曾经为了这个 ICMP redirect 的问题伤脑筋! 其实关闭 redirect 的这两个项目即可啊!)
要达成上面的功能你必须要这样做∶
[root@linux ~]#
vi somefile
for i in /proc/sys/net/ipv4/conf/*/rp_filter; do
echo "1" > $i
done
for i in /proc/sys/net/ipv4/conf/*/log_martians; do
echo "1" > $i
done
for i in /proc/sys/net/ipv4/conf/*/accept_source_route; do
echo "0" > $i
done
for i in /proc/sys/net/ipv4/conf/*/accept_redirects; do
echo "0" > $i
done
for i in /proc/sys/net/ipv4/conf/*/send_redirects; do
echo "0" > $i
done
[root@linux ~]#
sh somefile
7.filter防火墙的一个实例
[root@linux iptables]#
vi iptables.rule
#!/bin/bash
# 请先输入您的相关参数,不要输入错误了!
EXTIF="eth1" # 这个是可以连上 Public IP 的网路介面
INIF="eth0" # 内部 LAN 的连接介面;若无请填 ""
INNET="192.168.1.0/24" # 内部 LAN 的网域,若没有内部 LAN 请设定为 ""
export EXTIF INIF INNET
# 第一部份,针对本机的防火墙设定!###########################
# 1. 先设定好核心的网路功能∶
echo "1" > /proc/sys/net/ipv4/tcp_syncookies
echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
for i in /proc/sys/net/ipv4/conf/*/rp_filter; do
echo "1" > $i
done
for i in /proc/sys/net/ipv4/conf/*/log_martians; do
echo "1" > $i
done
for i in /proc/sys/net/ipv4/conf/*/accept_source_route; do
echo "0" > $i
done
for i in /proc/sys/net/ipv4/conf/*/accept_redirects; do
echo "0" > $i
done
for i in /proc/sys/net/ipv4/conf/*/send_redirects; do
echo "0" > $i
done
# 2. 清除规则、设定预设政策及开放 lo 与相关的设定值
PATH=/sbin:/usr/sbin:/bin:/usr/bin; export PATH
iptables -F
iptables -X
iptables -Z
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state RELATED -j ACCEPT
# 3. 启动额外的防火墙 script 模组
if [ -f /usr/local/virus/iptables/iptables.deny ]; then
sh /usr/local/virus/iptables/iptables.deny
fi
if [ -f /usr/local/virus/iptables/iptables.allow ]; then
sh /usr/local/virus/iptables/iptables.allow
fi
if [ -f /usr/local/virus/httpd-err/iptables.http ]; then
sh /usr/local/virus/httpd-err/iptables.http
fi
iptables -A INPUT -m state --state ESTABLISHED -j ACCEPT
# 4. 允许某些类型的 ICMP 封包进入
AICMP="0 3 3/4 4 11 12 14 16 18"
for tyicmp in $AICMP
do
iptables -A INPUT -i $EXTIF -p icmp --icmp-type $tyicmp -j ACCEPT
done
# 5. 允许某些服务的进入,请依照您自己的环境开启
# iptables -A INPUT -p TCP -i $EXTIF --dport 22 -j ACCEPT # SSH
# iptables -A INPUT -p TCP -i $EXTIF --dport 25 -j ACCEPT # SMTP
# iptables -A INPUT -p UDP -i $EXTIF --sport 53 -j ACCEPT # DNS
# iptables -A INPUT -p TCP -i $EXTIF --sport 53 -j ACCEPT # DNS
# iptables -A INPUT -p TCP -i $EXTIF --dport 80 -j ACCEPT # WWW
# iptables -A INPUT -p TCP -i $EXTIF --dport 110 -j ACCEPT # POP3
# iptables -A INPUT -p TCP -i $EXTIF --dport 443 -j ACCEPT # HTTPS
# 第二部份,针对后端主机的防火墙设定!##############################
# 1. 先载入一些有用的模组
modules="ip_tables iptable_nat ip_nat_ftp ip_nat_irc ip_conntrack
ip_conntrack_ftp ip_conntrack_irc"
for mod in $modules
do
testmod=`lsmod | grep "${mod} "`
if [ "$testmod" == "" ]; then
modprobe $mod
fi
done
# 2. 清除 NAT table 的规则吧!
iptables -F -t nat
iptables -X -t nat
iptables -Z -t nat
iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P POSTROUTING ACCEPT
iptables -t nat -P OUTPUT ACCEPT
# 3. 开放成为路由器,且为 IP 分享器!
if [ "$INIF" != "" ]; then
iptables -A INPUT -i $INIF -j ACCEPT
echo "1" > /proc/sys/net/ipv4/ip_forward
if [ "$INNET" != "" ]; then
for innet in $INNET
do
iptables -t nat -A POSTROUTING -s $innet -o $EXTIF -j MASQUERADE
done
fi
fi
# 如果你的 MSN 一直无法连线,或者是某些网站 OK 某些网站不 OK,
# 可能是 MTU 的问题,那你可以将底下这一行给他取消注解来启动 MTU 限制范围
# iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss /
# --mss 1400:1536 -j TCPMSS --clamp-mss-to-pmtu
# 4. 内部伺服器的设定∶
# iptables -t nat -A PREROUTING -p tcp -i $EXTIF --dport 80 /
# -j DNAT --to 192.168.1.210:80
[root@linux iptables]#
vi iptables.allow
#!/bin/bash
# 底下则填写你允许进入本机的其他网域或主机啊!
iptables -A INPUT -i $EXTIF -s 140.116.44.0/24 -j ACCEPT
# 底下则是关于抵挡的档案设定法!
[root@linux iptables]#
vi iptables.deny
#!/bin/bash
# 底下填写的是『你要抵挡的那个咚咚!』
iptables -A INPUT -i $EXTIF -s 140.116.44.254 -j DROP
[root@linux iptables]#
chmod 700 iptables.*
参考:
鸟哥的私房菜 http://linux.vbird.org