翻译自:http://chiralsoftware.com/linux-system-administration/ubuntu-firewall-iptables.seam
第一次翻译,望见谅。
在这篇文章里我们将在Ubuntu Server 8.04上建立一个简单的防火墙,
建立防火墙有两个目的:
1. 屏蔽所有的端口除了少部分被提供给服务或程序用的。
2. 映射从80进入的端口到另一个端口8080,让我们的Java Web Server可以以非root帐号运行起来。(因为80端口小于1024,凡是小于1024的端口必须以root帐号权限启动)
所有这些设置必须在一台远程的服务器上完成,那么我们务必在操作时要小心不要把自己屏蔽在防火墙之外。
列一下我们需要的服务和对应的 port(端口):
1. http, port 80
2. smtp, port 25
3. sshd, port 22
4. smtp, 转发邮件服务, 还开了个在 port 10025
5. imap, 加密的邮件服务, port 143
6. ftp, 我们需要FTP上传下载文件的服务。
7. OpenVPN 也将需要留着备用。
关键是我们是在远程操作,所以在操作的时候切记不要把我们自己屏蔽在防火墙外面。保守点的好办法是弄一个VirtualBox虚拟机,那样更容易测试配置而且不会有被屏蔽的危险。
作者尝试用ufw,大致内容是8.04自带的工具ufw,一个很简易的防火墙,在做NAT端口转发的时候不那么好用,所以他放弃了,还是遵循老路用”iptables”。
直接使用iptables
系统刚弄好的时候iptables的规则是空的,也就是iptables没有激活。开始先允许在loopback(环路)上的所有流量。如果你不这么做,很多进程可能无法工作,像Postfix,MySQL:
iptables -I INPUT 1 -i lo -j ACCEPT
然后创建一条规则允许建立tcp连接保持它的连接状态:
iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
然后添加我们想要的独立端口(上面提到过):
iptables -A INPUT -p tcp –dport 80 -j ACCEPT
iptables -A INPUT -p tcp –dport 22 -j ACCEPT
添加一个“drop-all(抛弃所有连接)”在chain(链路)的最后一行,其实就是只接受上面开放的端口,屏蔽掉其余所有的端口。
iptables -A INPUT -j DROP
现在这事一个最基本的服务器防火墙配置。但这里还是有个问题,我们的web server都是基于JAVA的(JBoss AS or Tomcat)。纯JAVA的应用没有办法以非root启动80端口,因为不能变更用户。Apache HTTPD(使用人数最多的Web server,但和以上两种基于JAVA的web server有本质的区别)它可以在绑定后以非root用户启动,因为它能被系统调用,而JAVA进程不能。
因此我们需要找些方法跑JAVA服务,并使其能通过80端口。解决方法是port redirection(端口重定向)。
注意这个“privileged ports(授权端口)”的概念在Linux的历史中比起其他简单的方法会引起更多的安全顾虑,这个还是Linux很古老的设计问题。绝对应该被移除的。数据从其他端口进来是最不安全的,故至少要有权限才能去处理。Linux是如何做的呢?完全相反,很不幸,如果你让非root进程绑定授权的端口,那不好的事情就会发生,这个问题到现在还在,但是有如此多的系统管理员相信那种陈词滥调。这些管理员没人相信这个问题能够确切地解释那些不好的事情的发生,他们还继续坚信着。事实上这是基于奇怪的心里暗示,root是如此的重要,因为root是最大权限的帐户,权限最大的用户应该做最重要的事,对否?(到这里为止都是反问和讽刺)很不幸这彻头彻尾都错了,任务进程应该被分配最少的权限去完成。Postifx(一个邮件服务器)是一个最小化权限的最好的例子。Postfix是一套小的,独立的,单一目标的任务,当然只要最小的权限即可,无需root,大部分只要在chroot(可以理解为类似于root,但是权限小很多,对系统不会有任何影响)环境下即可。
幸运的是iptables没有那样的问题。
用一条命令创建一个redirection rule(重定向规则):
iptables -t nat -A PREROUTING -p tcp –dport 80 -j REDIRECT –to-port 8080
但是这条规则无法工作。发生了什么,prerouting rules生效在input chain之前。意思是当packet(数据包)被input chain校验之前,80端口就已经被映射到了8080。 这个问题是因为没有规则说允许开放8080端口。我们需要添加一个这样的规则在DROP命令之前。
我们可以使用iptables的插入方法做这个。首先输入 iptables -L 显示所有的chain, 然后在DROP那行前为8080插入规则:
iptables -I INPUT 3 -p tcp –dport 8080 -j ACCEPT
这条规则插在第3个位置,这里注意我们没有真正使用到允许80端口的规则,因为在这个规则被触发前80端口被映射到了8080上,所以呢我们可以回头把这条允许80端口访问的规则给删了。当然啦,即使规则留在这里也不会有什么问题。
测试下,应该能访问到tomcat server了(默认设置Tomcat使用的是8080端口),此时tomcat是以非root用户运行的,从外面访问80端口即可。这里值得注意的是如果想从loopback(环路,也就是127.0.0.1)通过80端口访问tomcat是不行的,因为需要为环路也指定规则:
iptables -t nat -A OUTPUT -o lo -p tcp –dport 80 -j REDIRECT –to-port 8080
保存规则
保存到自己文件路径:
iptables-save > /etc/iptables.rules
添加网络启动时自动启动iptables,需要修改此文件/etc/network/interfaces,添加如下一行:
pre-up iptables-restore < /etc/iptables.rules
给个模版做参考,完成后就是这个样子:
iface eth0 inet static
address 333.333.333.333
netmask 255.255.255.0
gateway 333.333.333.1
pre-up iptables-restore < /etc/iptables.rules
测试
重启机器确保一切都正常,一旦机器放到产品环境下你不会想让机器起不来的。(所以测试还是很重要的)
关于JBoss AS绑定地址
Tomcat本身是绑在主机的对外地址上(指的是监听着所有的网卡,地址是:0.0.0.0)。而JBoss AS默认是只监听本机环路的连接(是指127.0.0.1)。我们所想要的就是为它监听对外的地址在8080端口上。(这应该算是个回家作业=。=!)