假设您的 Linux 主机提供了 WWW 的服务,那麼自然就要针对 port 80 来啟用通过的封包规则,但是您发现 IP 来源為 192.168.100.100 老是恶意的尝试入侵您的系统,所以您想要将该 IP 拒绝往来,最后,所有的非 WWW 的封包都给他丢弃,就这三个规则来说,您要如何设定防火墙检验顺序呢?
filter:主要跟 Linux 本机有关,这个是预设的 table 喔!
INPUT:主要与封包想要进入我们 Linux 本机有关;
OUTPUT:主要与我们 Linux 本机所要送出的封包有关;
FORWARD:这个咚咚与 Linux 本机比较没有关係,他可以封包『转递』到后端的电脑中,与 nat 这个 table 相关性很高。
nat:这个表格主要在用作来源与目的之 IP 或 port 的转换, 与 Linux 本机较无关,主要与 Linux 主机后的区域网路内的电脑较有相关。
PREROUTING:在进行路由判断之前所要进行的规则(DNAT/REDIRECT)
POSTROUTING:在进行路由判断之后所要进行的规则(SNAT/MASQUERADE)
OUTPUT:与发送出去的封包有关
本机端的 1024:65535 到远端的 port 22 必须要放行 (OUTPUT 链);
远端主机 port 22 到本机的 1024:65535 必须放行 (INPUT 链);
这会很麻烦!因為如果你要连线到 10 部主机的 port 22 时,假设 OUTPUT 為预设开啟 (ACCEPT), 你依旧需要填写十行规则,让那十部远端主机的 port 22 可以连线到你的本地端主机上。 那如果开啟全部的 port 22 呢?又担心某些恶意主机会主动以 port 22 连线到你的机器上! 同样的道理,如果你要让本地端主机可以连到外部的 port 80 (WWW 服务),那就更不得了~ 这就是网路连线是双向的一个很重要的概念!
好在我们的 iptables 免除了这个困扰!他可以透过一个状态模组来分析 『这个想要进入的封包是否為刚刚我发出去的回应?』 如果是刚刚我发出去的回应,那麼就可以予以接受放行!哇!真棒!这样就不用管远端主机是否连线进来的问题了! 那如何达到呢?看看底下的语法:
[root@linux ~]# 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
所以说,如果你的 Linux 主机只想要作為 client 的用途,不许所有主动对你连线的来源, 那麼你可以这样做即可:
清除所有已经存在的规则 (iptables -F...)
设定预设政策,除了 INPUT 预设為 DROP 其他為预设 ACCEPT;
开放本机的 lo 可以自由放行;
设定有相关的封包状态可以连线进入本机。
这就是最最阳春的防火墙,你可以透过第二步骤抵挡所有远端的来源封包, 而透过第四步骤让你要求的远端主机回应封包可以进入, 加上让本机的 lo 这个内部迴圈装置可以放行,嘿嘿!一部 client 专用的防火墙规则就 OK 了! 你可以在某个 script 上面这样做即可:
#!/bin/bash
PATH=/sbin:/bin:/usr/sbin:/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 -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
#iptables -A INPUT -i eth0 -s 192.168.1.0/24 -j ACCEPT
那如果区域网路内有其他的主机时,再将上表最后一行的 # 取消,就可以接受来自本地 LAN 的其他主机的连线了。 而如果你担心某些 LAN 内的恶意来源主机会主动的对你连线时,那你还可以针对信任的本地端主机的 MAC 进行过滤! 同样是使用状态模组!这次的状态则是 MAC 的比对。举例来说:
范例一:针对区域网路内的 aa:bb:cc:dd:ee:ff 主机开放其连线
[root@linux ~]# iptables -A INPUT -m mac --mac-source aa:bb:cc:dd:ee:ff \
> -j ACCEPT
参数:
--mac-source :就是来源主机的 MAC 啦!
先由主机向外面主动连线试看看;
再由私有网域内的 PC 向外面主动连线试看看;
最后,由 Internet 上面的主机,主动连线到您的 Linux 主机试看看;
一步一步作下来,看看问题出在哪裡,然后多多的去改进、改良!基本上, 网路上目前很多的资料可以提供您不错的参考了!这一篇的设定写的是很简单, 大部分都还在介绍阶段而已!希望对大家有帮助! 鸟哥在参考资料当中列出几个有用的防火墙网页, 希望大家有空真的要多多的去看看!会很有帮助的!
我们在前一章谈到所谓的阻断式服务 (DoS) 攻击法当中的一种方式,就是利用 TCP 封包的 SYN 三向交握原理所达成的, 这种方式称為 SYN Flooding 。那如何预防这种方式的攻击呢?我们可以啟用核心的 SYN Cookie 模组啊! 这个 SYN Cookie 模组可以在系统用来啟动随机连线的埠口 (1024:65535) 即将用完时自动啟动。
当啟动 SYN Cookie 时,主机在发送 SYN/ACK 确认封包前,会要求 Client 端在短时间内回覆一个序号, 这个序号包含许多原本 SYN 封包内的资讯,包括 IP、port 等。若 Client 端可以回覆正确的序号, 那麼主机就确定该封包為可信的,因此会发送 SYN/ACK 封包,否则就不理会此一封包。
透过此一机制可以大大的降低无效的 SYN 等待埠口,而避免 SYN Flooding 的 DoS 攻击说! 那麼如何啟动这个模组呢?很简单,这样做即可:
[root@linux ~]# echo "1" > /proc/sys/net/ipv4/tcp_syncookies
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_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
事实上,我们在设定防火墙的时候,不太可能会一个一个指令的输入,通常是利用 shell scripts 来帮我们达成这样的功能吶!底下是利用上面的流程图所规划出来的防火墙 scripts,您可以参考看看, 但是您需要将环境修改成适合您自己的环境才行喔!
[root@linux ~]# mkdir -p /usr/local/virus/iptables
[root@linux ~]# cd /usr/local/virus/iptables
[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
# 第二部份,针对后端主机的防火墙设定!##############################
# 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
# 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
呼呼!终於来到这个地方了!我们準备要架设一个路由器的延伸伺服器,就称之為 NAT 主机。 NAT 是什麼呢?简单的说,你可以称他為内部 LAN 主机的『 IP 分享器』啦!
NAT 的全名是 Network Address Translation,字面上的意思是『网路位址的转换』。由字面上的意思我们来想一想, TCP/IP 的网路封包不是有 IP 位址吗?那 IP 位址不是有来源与目的吗?我们的 iptables 指令就能够修改 IP 封包的表头资料, 嘿嘿!连目标或来源的 IP 位址都可以修改呢!甚至连 TCP 封包表头的 port number 也能修改!真是有趣!
NAT 主机的功能可以达到类似图二所介绍的类似 IP 分享的功能之外, 还可以达到类似图四所介绍的 DMZ (非军事区) 的功能!这完全取决於我们的 NAT 是修改: (1)来源 IP 还是 (2)目标 IP !底下我们就来聊一聊吧! ^_^
你应该有听说过 IP 分享器这个玩意儿,他可以让你家庭裡的好几部主机同时透过一条 ADSL 网路连线到 Internet 上面, 例如图二连线的方式来说,那个 Linux 主机就是 IP 分享器啦!那麼他是如何达到 IP 分享的功能?就是透过 NAT 表格的 POSTROUTING 来处理的。假设你的网路佈线如图二所示, 那麼 NAT 主机是如何处理这个封包的呢?
用户端所发出的封包表头中,来源会是 192.168.1.100 ,然后传送到 NAT 这部主机;
NAT 这部主机的内部介面 (192.168.1.2) 接收到这个封包后,会主动分析表头资料, 因為表头资料显示目的并非 Linux 本机,所以开始经过路由, 将此封包转到可以连接到 Internet 的 Public IP 处;
由於 private IP 与 public IP 不能互通,所以 Linux 主机透过 iptables 的 NAT table 内的 Postrouting 链将封包表头的来源偽装成為 Linux 的 Public IP ,并且将两个不同来源 (192.168.1.100 及 public IP) 的封包对应写入暂存记忆体当中, 然后将此封包传送出去了;
此时 Internet 上面看到这个封包时,都只会知道这个封包来自那个 Public IP 而不知道其实是来自内部啦。 好了,那麼如果 Internet 回传封包呢?又会怎麼作?
图十一、SNAT 封包接收的示意图
在 Internet 上面的主机接到这个封包时,会将回应资料传送给那个 Public IP 的主机;
当 Linux NAT 主机收到来自 Internet 的回应封包后,会分析该封包的序号,并比对刚刚记录到记忆体当中的资料, 由於发现该封包為后端主机之前传送出去的,因此在 NAT Prerouting 链中,会将目标 IP 修改成為后端主机,亦即那部 192.168.1.100,然后发现目标已经不是本机 (public IP), 所以开始透过路由分析封包流向;
封包会传送到 192.168.1.2 这个内部介面,然后再传送到最终目标 192.168.1.100 机器上去!
经过这个流程,您就可以发现到,所有内部 LAN 的主机都可以透过这部 NAT 主机连线出去, 而大家在 Internet 上面看到的都是同一个 IP (就是 NAT 那部主机的 public IP 啦!), 所以,如果内部 LAN 主机没有连上不明网站的话,那麼内部主机其实是具有一定程度的安全性的啦! 因為 Internet 上的其他主机没有办法主动攻击你的 LAN 内的 PC 嘛!所以我们才会说, NAT 最简单的功能就是类似 IP 分享器啦!那也是 SNAT 的一种。
Tips:
NAT 主机与路由器有啥不同?基本上,NAT 主机一定是路由器,不过, NAT 主机由於会修改 IP 表头资料, 因此与单纯转递封包的路由器不同。最常见的 IP 分享器就是一个路由器,但是这个 IP 分享器一定会有一个 Public IP 与一个 Private IP,让 LAN 内的 Private IP 可以透过 IP 分享器的 Public IP 传送出去喔! 至於路由器通常两边都是 Public IP 或同时為 Private IP。
SNAT 主要是应付内部 LAN 连接到 Internet 的使用方式,至於 DNAT 则主要用在内部主机想要架设可以让 Internet 存取的伺服器啦! 就有点类似图四的 DMZ 内的主机啊!底下也先来谈一谈 DNAT 的运作吧!
图十二、DNAT 的封包传送示意图
如上图十二所示,假设我的内部主机 192.168.1.210 啟动了 WWW 服务,这个服务的 port 开啟在 port 80 , 那麼 Internet 上面的主机 (61.xx.xx.xx) 要如何连接到我的内部伺服器呢?当然啦, 还是得要透过 Linux NAT 主机嘛!所以这部 Internet 上面的机器必须要连接到我们的 NAT 的 public IP 才行。
外部主机想要连接到目的端的 WWW 服务,则必须要连接到我们的 NAT 主机上头;
我们的 NAT 主机已经设定好要分析出 port 80 的封包,所以当 NAT 主机接到这个封包后, 会将目标 IP 由 public IP 改成 192.168.1.210 ,且将该封包相关资讯记录下来,等待内部伺服器的回应;
上述的封包在经过路由后,来到 private 介面处,然后透过内部的 LAN 传送到 192.168.1.210 上头!
192.186.1.210 会回应资料给 61.xx.xx.xx ,这个回应当然会传送到 192.168.1.2 上头去;
经过路由判断后,来到 NAT Postrouting 的链,然后透过刚刚第二步骤的记录,将来源 IP 由 192.168.1.210 改為 public IP 后,就可以传送出去了! (类似图十的状态!)。
其实整个步骤几乎就等於 SNAT 的反向传送哩!这就是 DNAT 囉!很简单吧!
--------------------------------------------------------------------------------
最阳春 NAT 主机: IP 分享功能
在 Linux 的 NAT 主机服务当中,最常见的就是类似图二的 IP 分享器功能了。 而由刚刚的介绍你也该知道,这个 IP 分享器的功能其实就是 SNAT 啦!作用就只是在 iptables 内的 NAT 表格当中,那个路由后的 POSTROUTING 链进行 IP 的偽装就是了。另外, 你也必须要瞭解,你的 NAT 主机必须要有一个 public IP 介面,以及一个内部 LAN 连接的 private IP 介面才行。
同样的,我的假设是这样的:
外部介面使用 eth1 ,这个介面具有 public IP 喔;
内部介面使用 eth0 ,假设这个 IP 為 192.168.1.2 ;
记住!当你利用前面几章谈到的资料来设定你的网路参数后,务必要进行路由的检测, 因為在 NAT 主机的设定方面,最容易出错的地方就是路由了!尤其是在拨皆產生 ppp0 这个对外介面的环境下, 这个问题最严重。反正你要记得:『如果你的 public IP 取得的方式是拨接或 cable modem 时,你的设定档 /etc/sysconfig/network, ifcfg-eth0, ifcfg-eth1 等档案,千万不要设定 GATEWAY 啦!』否则就会出现两个 default gateway ,反而会造成问题。