建立网路防火墙

在进行这个部分之前,我们需要你已经安装了iptables。

防火墙技术简介

一般的说,防火墙技术是用一个计算机作防火墙将一个网路保护起来 避免外部的有害登陆。在外部看来防火墙就是一个有故障的节点,但是这个节点 大大减轻了网管的工作量。

如果每一个监视进程或者服务都非常理想而完美的设置而可以免疫像, 缓冲溢出,等各种可以预料的安全问题。然后你信任每一个登陆系统的用户都 都非常的善意,那么你就不需要一个防火墙了。然而在现实的网路中, 守护进程可能有错误的设置,攻击重要的服务可能非常的容易,你可能要限制哪个服务 只有哪个计算机才可以登陆,或者哪个服务和软件可以通过互联网登陆,更简单的说,你并不 信任这些软件和你的用户们。在这种情况下,你就必须要安装一个防火墙了。

并不是说有了防火墙就可以,不去认真设置软件,不注意那些 有害的设置,或者防火墙可以避免任何对你互联网服务的攻击,而不去 管那些新出的补丁。除了建立一个防火墙,你还要保证所有程序和服务都 被即时的更新并且设置的很好,防火墙不是万能的。

防火墙这个词的含义

防火墙有好几层意思。

个人防火墙

是一套或者一个程序,比如windows下的Symantec的商业软件。 这些程序或者至少声明可以保护一个家庭网路和计算机不被非法侵入。对于那些 一直使用宽带链接而又不知到他们的计算机会怎么样被侵入或者如何避免的用户来说 这样的软件再合适不过。

IP伪装路由

是一个放置在外部网路和内部网路之间的一台计算机。为了尽量减小 潜在的危害,防火墙只有一个原则就是:保护内部网。近管不是万无一失,但是一般认为 作了路由和IP伪装之后是比较安全的。[1]

BusyBox

作路由和IP伪装的计算机往往都是一台你淘汰下来甚至已经忘掉的计算机,而又 同时默默无闻的提供着各种服务,比如网路缓冲,邮件。这样的事情在家庭网路里面非常常见。 但是从安全的角度来看是绝不安全的。因为将服务器和路由放在一台机器上设置是非常复杂的。

非军事用途的防火墙(就不细说了)

计算机扮演着IP伪装或者路由的角色,但是有大量的公共登陆链接到 你的每一个网路分枝。因为公共IP的物理结构,他们既不能说是内网也不能说成是外网。 这样的服务器必须要从内外网都登陆方便。这个时候防火墙就保护内,外两个网路。

数据包过滤 / 部分开放网路BusyBox]

作路由或者IP伪装,允许对一些指定的服务的登陆。有时只允许内网用户 或者计算机登陆。经常用在保护商业的高度机密不被不可信的雇员得到。这个在linux 2.2的时代是一种非常常见的防火墙设置。现在仍然可以如此设置,但是 脚本会非常复杂和冗长。

免责声明

作者和linux from scratch小组都不对 按照本文设置而引发的损失负责。

这个文档旨在介绍如何搭建防火墙,但并不是一个完整的安全系统指南。 防火墙是一个非常复杂的问题。这里引用的脚本不过是说明防火墙的一些例子, 并不完善。

这个文章不过是对你开始设置放火墙的一些提示。

一定要对这些脚本根据实际需要作合理的改动,以优化设置。同时还必须 认真的在动手之前认真学习iptable的文档。在文章的最后,推荐您阅读 进一步学习防火墙的知识 。在这个链接里面包含了很多制作适合自己情况的防火墙的知识。

使内核支持防火墙

如果你想让你的linux系统可以作防火墙,那么首先要 确保内核编译了相关的选项。 [2].

如何设置你的内核,选择哪些功能编译到内核内部,哪些编译为外部模块,取决于你的 经验和喜好。引用的脚本假设模块已经被事先调入。

表格 4-1. 内核支持防火墙的关键设置

Networking options:Network packet filtering =CONFIG_NETFILTER
 Unix domain sockets =CONFIG_UNIX
 IP: TCP/IP networking =CONFIG_INET
 IP: advanced router =CONFIG_IP_ADVANCED_ROUTER
 IP: verbose route monitoring =CONFIG_IP_ROUTE_VERBOSE
 IP: TCP Explicit Congestion Notification support =CONFIG_INET_ECN
 IP: TCP syncookie support =CONFIG_SYN_COOKIES
  IP: Netfilter Configuration:every option=CONFIG_IP_NF_*
 去掉:

ipchains (2.2-style) support ipfw-adm (2.0-style) support

w\CONFIG_IP_NF_COMPAT_*
 Fast switching一定要关闭这个功能,因为它会在防火墙上面开一个后门。w\CONFIG_NET_FASTROUTE

现在我们开始打造自己的防火墙

个人防火墙

个人防火墙应该可以使你联接到互联网上的任何的服务。同时使你的计算机和数据受到保护。

下面是一个从 Rusty Russell 的 recommendation from the Linux 2.4 Packet Filtering HOWTO 稍加改动的脚本。:

cat > /etc/rc.d/init.d/firewall << "EOF"
#!/bin/sh

#  $rc_base/init.d/firewall 开始

# 挂载所需内核模块(如果内嵌到内核的话就不用了)
modprobe ip_tables
modprobe iptable_filter
modprobe ip_conntrack
modprobe ip_conntrack_ftp
modprobe ipt_state
modprobe ipt_LOG

# 只允许本地联接
iptables -A INPUT  -i lo -j ACCEPT
# 允许到任何IP的联接(等同于 -P ACCEPT)
iptables -A OUTPUT -j ACCEPT

# 允许对已经建立的联接的回应
# 允许建立和已经建立的联接相关的联接(如:active-ftp)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 将其他的信息都记录,最新的windows安全漏洞是什么?
iptables -A INPUT -j LOG --log-prefix "FIREWALL:INPUT "

#建立清晰的规则:任何东西都不接受 > /dev/null
iptables -P INPUT    DROP
iptables -P FORWARD  DROP
iptables -P OUTPUT   DROP

# 设置动态IP
echo 2 > /proc/sys/net/ipv4/ip_dynaddr

# 关闭 ExplicitCongestionNotification
echo 0 > /proc/sys/net/ipv4/tcp_ecn

# End $rc_base/init.d/firewall
EOF

他的脚本比较简单。将丢掉所有从外部进入而又不是起源于你计算机的包。 但是只要你是简单的上网,并不容易达到这个限制。

如果你总在联接ftp的时候出现时滞,可以看看:BusyBox - example no. 4.

如果你在计算机上运行服务,这些服务将不能从外部接入。想 允许联接这些服务比如ssh或者ping,可以看看这个: BusyBox.

IP伪装路由

一个真正的防火墙有两个界面,一个联接内部网,比如eth0, 另外一个联接互联网ppp0。为了使这个计算机尽量安全而不被侵入,要保证 没有任何服务在上面运行,特别是X11不要运行。而且这个计算机不能接入任何不安全的 服务。

cat > /etc/rc.d/init.d/firewall << "EOF"
#!/bin/sh

# Begin $rc_base/init.d/firewall

echo
echo "You're using the example-config for a setup of a firewall"
echo "from the firewalling-hint written for LinuxFromScratch."
echo "This example is far from being complete, it is only meant"
echo "to be a reference."
echo "Firewall security is a complex issue, that exceeds the scope"
echo "of the quoted configuration rules."
echo "You can find some quite comprehensive information"
echo "about firewalling in Chapter 4 of the BLFS book."
echo "http://beyond.linuxfromscratch.org/"
echo
#译文:你正在使用一个LFS防火墙提示中的防火墙的配置样例。这个例子远不成熟。
#只是一个参考。防火墙的问题是非常复杂的,已经超越了配置规则的范畴。
#你可以在BLFS文档的第6章中找到颇为详尽的信息。


# 挂载iptable模块(如果内嵌到内核的话就不用了)

modprobe ip_tables
modprobe iptable_filter
modprobe ip_conntrack
modprobe ip_conntrack_ftp
modprobe ipt_state
modprobe iptable_nat
modprobe ip_nat_ftp
modprobe ipt_MASQUERADE
modprobe ipt_LOG
modprobe ipt_REJECT

# 只允许本地联接
iptables -A INPUT  -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# 允许转发
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m state --state NEW -i ! ppp+	 -j ACCEPT

# 进行IP伪装(如果内网不使用单独的IP就不用了。)
iptables -t nat -A POSTROUTING -o ppp+ -j MASQUERADE

# 对所有的东西作记录以纠错 ( 是所有的规则的最后一条,在
#DROP/REJECT之前)
iptables -A INPUT   -j LOG --log-prefix "FIREWALL:INPUT  "
iptables -A FORWARD -j LOG --log-prefix "FIREWALL:FORWARD"
iptables -A OUTPUT  -j LOG --log-prefix "FIREWALL:OUTPUT "

#设置一个清晰的规则
iptables -P INPUT   DROP
iptables -P FORWARD DROP
iptables -P OUTPUT  DROP

# 设置动态IP
echo 2 > /proc/sys/net/ipv4/ip_dynaddr

# 关闭 ExplicitCongestionNotification
echo 0 > /proc/sys/net/ipv4/tcp_ecn

# 开启 TCPsyncookies
echo 1 > /proc/sys/net/ipv4/tcp_syncookies

# activate Route-Verification = IP-Spoofing_protection
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do
	echo 1 > $f
done

# 开启 IP-Forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
EOF

使用这个脚本,你的内部网应该不会受到外部的攻击了。没人可以 与内网的任何服务建立联接,如果内网被IP伪装,外部网路甚至找不到他们。 同时,你的防火墙也基本没什么弱点,因为上面没有运行任何黑客可以 攻击的服务。

如果你连往互联网的界面不是PPP,需要把 ppp+ 改为你使用的界面。 如果你使用同一个界面联接内网和外网,则需要在两个地方使用界面的真是名称 eth0

如果需要更多的安全防护,可以参考 进一步学习防火墙的知识

BusyBox

这个方案和IP伪装路由这个区别不大, 但是更偏重于你想在内部网路中使用一些服务,比如在另外内部电脑上面操作你的电脑, 或者 把你的计算机作成一个代理服务器或者域名服务器。注:如何保护一个在互联网(不是内部网)上提供 服务的服务器超出了本文的范围,具体可以参见:免责声明.

需要注意的是,开启或者提供的服务越多,你的计算机就越不安全,同时配置 也将变得越复杂,因为你可能会错误配置一个服务,或者运行了一个有bug的服务器程序, 同时对防火墙的安全性的考验也就越大了。在这里可以找到更多的信息: IP伪装路由

如果你的服务不需要接驳互联网,比如内部的samba服务和域名服务,那么下面的设置 方法在安全的角度讲,就已经可以满足我们的需要了。就是在脚本的记录规则之前加入下面的几行:
iptables -A INPUT	-i ! ppp+				-j ACCEPT
iptables -A OUTPUT	-o ! ppp+				-j ACCEPT

如果你的守护进程需要链接网路,例如squid, 那么你通常需要把OUTPUT打开并且限制INPUT。
iptables -A INPUT	-m state --state ESTABLISHED,RELATED	-j ACCEPT
iptables -A OUTPUT						-j ACCEPT

但是我们一般还是建议把OUTPUT加一些限制。否则,你可能不能控制那些特洛伊木马式 的操作,或者可能全世界都可以知道你有一些服务没有设置好。

想要多增加一些保护,你就需要将INPUT和OUTPUT限制在那些必须使用的端口上。你的需要决定 需要打开哪些端口,一般的说你可以在日志文件里面的失败操作里面找出这些端口号。

看几个例子:

  1. 带网页缓存的Squid:

    iptables -A OUTPUT	-p tcp --dport 80			-j ACCEPT
    iptables -A INPUT	-p tcp --sport 80	-m state --state ESTABLISHED \
       -j ACCEPT

  2. 利用udp工作的带缓存的域名服务器(例如:dns缓存):

    iptables -A OUTPUT	-p udp --dport 53			-j ACCEPT
    iptables -A INPUT	-p udp --sport 53	-m state --state ESTABLISHED \
       -j ACCEPT

  3. 或者你想从互联网上其他的机器ping自己的计算机,就要这样设置:

    iptables -A INPUT	-p icmp	-m icmp --icmp-type echo-request	\
       -j ACCEPT
    iptables -A OUTPUT	-p icmp	-m icmp --icmp-type echo-reply	-j
    ACCEPT

  4. 如果你频繁的登陆FTP服务器或者经常聊天,你会觉得这样设置有些慢,这是因为这些服务会不断的 呼叫你计算机上一个互联网身份确认的守护进程来检测你登陆的用户名。同时这个互联网身份确认守护 进程也会降低你计算机的安全性,所以这里建议关掉这个进程,不会有什么不良影响。

    避免延迟,你可以屏蔽那些呼叫请求。

    iptables -A INPUT	-p tcp --dport 113			-j REJECT \
       --reject-with tcp-reset
    iptables -A OUTPUT	-p tcp --sport 113	-m state --state RELATED \
       -j ACCEPT

  5. 有些包近管是无害的,但还是应该丢掉,比如 超时,扫描的包:

    iptables -I INPUT 1	-p tcp	-m state --state INVALID	-j LOG \
       --log-prefix "FIREWALL:INVALID"
    iptables -I INPUT 2	-p tcp	-m state --state INVALID	-j
    DROP

  6. 所有外来的东西都要有自己的地址,同时就有了一个最 常见的攻击手段,叫IP伪装:

    iptables -t nat -A PREROUTING	-i ppp+	-s 10.0.0.0/8		-j DROP
    iptables -t nat -A PREROUTING	-i ppp+	-s 172.16.0.0/12	-j DROP
    iptables -t nat -A PREROUTING	-i ppp+	-s 192.168.0.0/16	-j
    DROP

  7. 为了简化调试同时避免其他人登陆你已经关闭了的 服务,你应该屏蔽那些被丢掉的包。

    很显然,这个工作需要在这些包被记录然后丢掉之后进行。

    iptables -A INPUT						-j REJECT
    iptables -A OUTPUT		-p icmp --icmp-type 3		-j ACCEPT

这里不过是向您展示了一下linux内核2.4版中新的防火墙代码的功能。更详细的 内容可以在man文档中找到。在设置中需要的端口号参见/etc/services,有时候 你可能还要找一下日志文件里面的 "try'n'error" in your logfile.

如果你在系统中增加了任何服务,或者想去登陆什么服务的话,都要 改变这些设置。

编者按

最后,我想再补充一点:就是黑客在攻击你系统上下的功夫大小取决于他想获得的 东西的价值。如果你准备好了为主机里面所有有价值的内容而对付那些潜在的威胁者的话。 也就用不着我下面的提醒了。

时刻小心!

    Henning Rohde

PS: 请不要忘记: 安全技术时刻都在发展。任何时候都不要放松警惕。

PPS: 如果哪些脚本有错误,请通知我,我会关注所有的问题。

更多信息

firewall.status

如果你想了解组成防火墙的流水线,从而更好的设置它。

cat > /etc/rc.d/init.d/firewall.status << "EOF"
#!/bin/sh

#  $rc_base/init.d/firewall.status 开始

echo "iptables.mangling:"
iptables -t mangle  -v -L -n --line-numbers

echo
echo "iptables.nat:"
iptables -t nat	    -v -L -n --line-numbers

echo
echo "iptables.filter:"
iptables	    -v -L -n --line-numbers
EOF

firewall.stop

关闭防火墙的脚本:

cat > /etc/rc.d/init.d/firewall.stop << "EOF"
#!/bin/sh

#  $rc_base/init.d/firewall.stop 开始

# 关闭 IP-Forwarding
echo 0 > /proc/sys/net/ipv4/ip_forward

iptables -Z
iptables -F
iptables -t nat         -F PREROUTING
iptables -t nat         -F OUTPUT
iptables -t nat         -F POSTROUTING
iptables -t mangle      -F PREROUTING
iptables -t mangle      -F OUTPUT
iptables -X
iptables -P INPUT       ACCEPT
iptables -P FORWARD     ACCEPT
iptables -P OUTPUT      ACCEPT
EOF

[1]

将从内部用户的数据包的IP头信息重写,叫它看起来是从防火墙发到互联网上的。

[2]

如果需要设置,编译,安装内核方面的帮助,可以看LFS文档的 第8章。 安装内核 并最后 使 linux可以启动 ; 需要重起来运行新内核。