使用FreeBSD配置基于ADSL的VPN防火墙(IPFILTER)网关
使用FreeBSD配置基于ADSL的VPN防火墙(IPFILTER)网关陈永光(Charlin) < charlin@88vip.com >
操作系统:FreeBSD5.1
IPFilter: v3.4.31
MPD:v3.13
我的目的是做一台ADSL拨号网关,这个网关上由MPD作为VPN网关的守护进程,使用PPTP协议作为传输协议,由于这台机器上有samba服务器,所以我无法开放我的所有端口,我必须封锁所有不需要的端口。正因为这样花了很长时间研究PPTP协议到底需要通过防火墙上的那些端口和那些协议。配置的目的已经告诉大家了,下面是配置的过程。
首先从ppp拨ADSL说起,如果您对于使用ppp连接PPPoE(也就是ADSL使用的连接方式)已经非常熟悉了,那就可以跳过这一段直接看后面的。
使用ppp连接PPPoE是非常简单的,FreeBSD在安装好之后你会在/etc/ppp/目录下看到一个叫做ppp.conf的文件,你把这个文件修改成下面的样子就可以连接PPPoE了,文件内容如下:
default:
# PPP over Ethernet
set device PPPoE:rl0 # rl0是联接ADSL的设备号
set speed sync
set mru 1492
set mtu 1492
set ctsrts off
# monitor line quality
enable lqr
# log just a bit
set log phase tun
# insert default route upon connection
add default HISADDR
# download /etc/resolv.conf
enable dns
set authname xxxxxxxx # xxxxxxxx是ADSL账号
set authkey ******* #*******是ADSL密码
第一部分是设置日志的方式和一些默认信息set device PPPoE:后面需要改成你的网卡的驱动,我的是Realtek的8139,所以就是rl0了,下面是设置最大发送/接受单元,PPPoE默认是1492。enable dns是打开从ISP服务端接收分配的DNS,后面是设置你的PPPoE帐号信息,请务必添加。
注意:标签后面的语句要有缩进,至少缩进一个空格,在帖子里可能看不到,大家要注意!
修改过配置文件之后你就可以用ppp -ddial来试验一下,如果连接上了网络就没问题了,在/etc/rc.local文件中添加下面一句就可以在开机的时候启动ppp拨号:
/usr/sbin/ppp –ddial
其中ppp的方式,可选的有auto ddial background等等,具体的信息可以从man ppp中获得。以上就是PPP拨PPPoE的配置,可以看到非常的简单。
下面一部分是启动IPFILTER的防火墙,这个需要修改默认得内核设置,同时使用MPD也需要对内核进行修改,所就在这里同时都修改了。重新编译内核需要经过如下步骤,首先进入/usr/src/sys/i386/conf/目录,里面有一个GENERIC,具体的说明信息我就不赘述了,我只讲一下我修改内核的过程。
首先
cp GENERIC ipfilter
编辑mykern增加如下的部分:
options NETGRAPH
options NETGRAPH_PPPOE
options NETGRAPH_SOCKET
options NETGRAPH_ETHER
options IPSTEALTH
options IPFILTER
options IPFILTER_LOG
options IPFILTER_DEFAULT_BLOCK
退出编辑器
config ipfilter
cd ../compile/ipfilter
make depend
make
make install
然后重新启动机器内核的更新就已经完成了。
这样IPFILTER的安装就已经完成了,我们先不打开防火墙,我们先配置mpd来建立PPTP的服务器。关于MPD的安装其实非常简单,你可以自己手动编译,但我还是推荐大家用ports来安装,因为我实在是想不出什么理由来不用ports安装:)如果你安装了ports到你的硬盘上,你通过下列步骤就可以完成mpd的安装了
cd /usr/ports/net/mpd
make install
make clean
安装完毕之后,ports会自动创建/usr/local/etc/mpd目录并把配置文件的样本存放在这个目录里面,可以通过修改已有的配置文件样本来完成对mpd的配置,以mpd.conf.sample为例,首先cp mpd.conf.sample mpd.conf然后修改下面的两个部分:
default:
load pptp
pptp:
new -i ng0 pptp pptp
set iface disable on-demand
set iface enable proxy-arp
set iface idle 1800
set bundle enable multilink
set link yes acfcomp protocomp
set link no pap chap
set link enable chap
set link keep-alive 10 60
set link mtu 1460
set ipcp yes vjcomp
set ipcp ranges 192.168.1.1/32 192.168.1.50/32
set ipcp dns 192.168.1.3
set ipcp nbns 192.168.1.4
#
# The five lines below enable Microsoft Point-to-Point encryption
# (MPPE) using the ng_mppc( netgraph node type.
#
set bundle enable compression
set ccp yes mppc
set ccp yes mpp-e40
set ccp yes mpp-e128
set ccp yes mpp-stateless
这个是sample里面的默认配置,下面对于需要修改的部分做出说明实际上我们需要修改只有三行,就是下面三行
set ipcp ranges 192.168.1.1/32 192.168.1.50/32
set ipcp dns 192.168.1.3
set ipcp nbns 192.168.1.4
第一行是设置你的本地VPN网关的地址,如果你是像我一样用NAT来区分内外网的话这个应该是网关的内网地址,后面的是对方拨入以后将会在内网获得的地址,这个地址倒是没有什么特殊要求,就是首先这个地址需要和内网处于一个网段,否则访问不了,第二后面可以设置一个掩码,来控制这个地址可能的范围,如果这个地址被占用了,将会分配一个再限定范围内的地址给客户端,这个范围由"/"后面的掩码来控制。
第二行是指定你内网使用的DNS服务器的地址,注意这个将会在用户连入的时候同内网地址一起被分配给用户第三行和第二行类似,是指定Netbios服务器的地址,如果内网没有WINS服务器这行可以不写。最后我还增加了一行命令,再不增加这个命令的时候mpd看起来也是正常运转的,但是我不太放心还是加了这行加密指令
set bundle enable encryption
下面我们还需要cp mpd.links.sample mpd.links稍微修改一下mpd.links
pptp:
set link type pptp
set pptp self 1.2.3.4
set pptp enable incoming
set pptp disable originate
上面的部分里面需要修改一下set pptp self 1.2.3.4这一行,这行是指定mpd的pptp服务器绑定在那个地址上面,如果是我们现在使用ppp拨叫ADSL的情况,会遇到网络界面改变,ip地址改变的情况,就不能定义这一句,所以针对我们的情况,我们要去掉这句,其他的我们就不用改了。
当然我们还要cp mpd.secret.sample mpd.secret修改一下mpd.secret文件这个文件定义了拨入用户的用户名和密码用户名写在前面,密码写在后面用引号引起来,就像下面这样,当然还可以指定这个用户必须从那个地址或者网段来拨入,就像下面的例子:
fred "fred-pw"
joe "foobar" 192.168.1.1
bob "\x34\"foo\n" 192.168.1.10/24
sample文件里面还有配置多用户登陆的情况下的样本,我就不用在写了,配置是一样的改完这些之后只要运行mpd -b就可以启动了由于考虑到安全原因我没有书写启动脚本在开机的时候启动mpd,因为对于防火墙来说在没有用的时候多开一个端口就多一份危险,但是也许很多人需要在开机的时候自动运行mpd,下面我还是提供一个启动脚本给大家,可以放在/usr/local/etc/rc.d/目录下面记住要加上执行权限。
#!/bin/sh
PREFIX=/usr/local
case "$1" in
start)
if [ -x ${PREFIX}/sbin/mpd -a -f ${PREFIX}/etc/mpd/mpd.conf ]; then
${PREFIX}/sbin/mpd -b
echo -n ' mpd '
fi
;;
stop)
killall mpd && echo -n ' mpd '
;;
*)
echo "Usage: 'basename $0' {start|stop}" >&2
;;
esac
exit 0
;
下面我们要开启防火墙来测试一下了,我们开启防火墙还需要在/etc/rc.local文件中添加以下命令:
sh /etc/adslip.sh
然后再创建/etc/adslip.sh脚本:
代码:
#!/bin/sh
###############################################################################
(未完) (接上)
#adslip.sh 是一个自动检测ADSL分配的IP地址和利用这个IP地址动态创建IPFILTER过
#滤规则的脚本。
#使用方法:
#步骤一:要确定使用adslip.sh脚本的服务器能正常使用ADSL拨号和IPFILTER能正常运
#行。
#步骤二:把adslip.sh脚本修改成你的实际网络情况。修改如下:
#内部网卡设备号、内部网段、服务器IP地址、ADSL拨号网络设备号或自己增加网络设备
#和相应的过滤规则。
#步骤三:把adslip.sh脚本拷贝到/etc目录里,和在/etc/rc.local文件中为入”sh /etc/adslip.sh”
#就可以了。
###############################################################################
#内部网卡设备号fxp0
INTARNDEV="fxp0"
INTARN=`ifconfig $INTARNDEV | grep inet | cut -d ' ' -f 2`
#内部网段192.168.168.0/24
INTARNNET="192.168.168.0/24"
#服务器IP地址
#注意:服务器IP地址为0.0.0.0时是不会做相应的服务映射,只在填写了正确的IP地址后才会映射到该IP地址上。
INTARNFTP="0.0.0.0" #FTP服务器
INTARNSSH="0.0.0.0" #SSH服务器
INTARNEMAIL="0.0.0.0" #EMAIL服务器
INTARNDNS="0.0.0.0" #DNS服务器
INTARNWEB="0.0.0.0" #WEB服务器
INTARNSSL="0.0.0.0" #SSL服务器
INTARNRTSP="0.0.0.0" #RTSP服务器
INTARNMYSQL="0.0.0.0" #MYSQL服务器
INTARNJABBER="0.0.0.0" #JABBER服务器
#ADSL拨号网络设备号tun0
ADSLDEV="tun0"
ADSLIP=`ifconfig $ADSLDEV | grep inet | cut -d ' ' -f 2`
until [ $ADSLIP ]
do
sleep 5
done
#动态生成ipnat.rules规则
echo '######################################################' > /etc/ipnat.rules
echo '#/etc/ipnat.rules #' >> /etc/ipnat.rules
echo '######################################################' >> /etc/ipnat.rules
echo ''
echo '#把所有的内部网络IP伪装成ADSL拨号IP' >> /etc/ipnat.rules
echo 'map '$ADSLDEV' '$INTARNNET' -> '$ADSLIP'/32 portmap tcp/udp 10000:65000' >> /etc/ipnat.rules
if [ $INTARNFTP != "0.0.0.0" ]
then
echo ''
echo '#把对ADSL拨号IP的FTP服务映射到服务网络的FTP服务器上' >> /etc/ipnat.rules
echo 'rdr '$ADSLDEV' '$ADSLIP'/32 port 20 -> '$INTARNFTP' port 20' >> /etc/ipnat.rules
echo 'rdr '$ADSLDEV' '$ADSLIP'/32 port 21 -> '$INTARNFTP' port 21' >> /etc/ipnat.rules
fi
if [ $INTARNSSH != "0.0.0.0" ]
then
echo ''
echo '#把对ADSL拨号IP的SSH服务映射到服务网络的网管工作站上' >> /etc/ipnat.rules
echo 'rdr '$ADSLDEV' '$ADSLIP'/32 port 22 -> '$INTARNSSH' port 22' >> /etc/ipnat.rules
fi
if [ $INTARNEMAIL != "0.0.0.0" ]
then
echo ''
echo '#把对ADSL拨号IP的EMAIL服务映射到服务网络的EMAIL服务器上' >> /etc/ipnat.rules
echo 'rdr '$ADSLDEV' '$ADSLIP'/32 port 25 -> '$INTARNEMAIL' port 25' >> /etc/ipnat.rules
echo 'rdr '$ADSLDEV' '$ADSLIP'/32 port 110 -> '$INTARNEMAIL' port 110' >> /etc/ipnat.rules
fi
if [ $INTARNDNS != "0.0.0.0" ]
then
echo ''
echo '#把对ADSL拨号IP的DNS服务映射到服务网络的DNS服务器上' >> /etc/ipnat.rules
echo 'rdr '$ADSLDEV' '$ADSLIP'/32 port 53 -> '$INTARNDNS' port 53' >> /etc/ipnat.rules
fi
if [ $INTARNWEB != "0.0.0.0" ]
then
echo ''
echo '#把对ADSL拨号IP的WEB服务映射到服务网络的WEB服务器上' >> /etc/ipnat.rules
echo 'rdr '$ADSLDEV' '$ADSLIP'/32 port 80 -> '$INTARNWEB' port 80' >> /etc/ipnat.rules
fi
if [ $INTARNSSL != "0.0.0.0" ]
then
echo ''
echo '#把对ADSL拨号IP的SSL服务映射到服务网络的SSL服务器上' >> /etc/ipnat.rules
echo 'rdr '$ADSLDEV' '$ADSLIP'/32 port 443 -> '$INTARNSSL' port 443' >> /etc/ipnat.rules
fi
if [ $INTARNRTSP != "0.0.0.0" ]
then
echo ''
echo '#把对ADSL拨号IP的RTSP服务映射到服务网络的RTSP服务器上' >> /etc/ipnat.rules
echo 'rdr '$ADSLDEV' '$ADSLIP'/32 port 554 -> '$INTARNRTSP' port 554' >> /etc/ipnat.rules
fi
if [ $INTARNMYSQL != "0.0.0.0" ]
then
echo ''
echo '#把对ADSL拨号IP的MYSQL服务映射到服务网络的MYSQL服务器上' >> /etc/ipnat.rules
echo 'rdr '$ADSLDEV' '$ADSLIP'/32 port 3306 -> '$INTARNMYSQL' port 3306' >> /etc/ipnat.rules
fi
if [ $INTARNJABBER != "0.0.0.0" ]
then
echo ''
echo '#把对ADSL拨号IP的JABBER(客户端口5222和服务器端口5269)服务映射到服务网络的JABBER服务器上' >> /etc/ipnat.rules
echo 'rdr '$ADSLDEV' '$ADSLIP'/32 port 5222 -> '$INTARNJABBER' port 5222' >> /etc/ipnat.rules
echo 'rdr '$ADSLDEV' '$ADSLIP'/32 port 5269 -> '$INTARNJABBER' port 5269' >> /etc/ipnat.rules
fi
#动态生成ipf.rules规则
echo '#######################################################' > /etc/ipf.rules
echo '#/etc/ipf.rules #' >> /etc/ipf.rules
echo '#######################################################' >> /etc/ipf.rules
echo '#阻塞所有存在安全问题的数据包'>> /etc/ipf.rules
echo 'block in log quick all with short' >> /etc/ipf.rules
echo 'block in log quick all with ipopts' >> /etc/ipf.rules
echo 'block in log quick all with frag' >> /etc/ipf.rules
echo 'block in log quick all with opt lsrr' >> /etc/ipf.rules
echo 'block in log quick all with opt ssrr' >> /etc/ipf.rules
echo '' >> /etc/ipf.rules
echo '#外部网络的数据只有FTP(使用20和21端口)、www、dns、smtp、pop3、mysql、ssh、rtsp、jabber和ssl的服务可以进入' >> /etc/ipf.rules
if [ $INTARNFTP != "0.0.0.0" ]
then
echo 'pass in quick on '$ADSLDEV' proto tcp from any to any port = 20 keep state' >> /etc/ipf.rules
echo 'pass in quick on '$ADSLDEV' proto tcp from any to any port = 21 keep state' >> /etc/ipf.rules
fi
if [ $INTARNSSH != "0.0.0.0" ]
then
echo 'pass in quick on '$ADSLDEV' proto tcp from any to any port = 22 keep state' >> /etc/ipf.rules
fi
if [ $INTARNEMAIL != "0.0.0.0" ]
then
echo 'pass in quick on '$ADSLDEV' proto tcp from any to any port = 25 keep state' >> /etc/ipf.rules
echo 'pass in quick on '$ADSLDEV' proto tcp from any to any port = 110 keep state' >> /etc/ipf.rules
fi
if [ $INTARNDNS != "0.0.0.0" ]
then
echo 'pass in quick on '$ADSLDEV' proto udp from any to any port = 53 keep state' >> /etc/ipf.rules
echo 'pass out quick on '$ADSLDEV' proto udp from any port = 53 to any keep state' >> /etc/ipf.rules
fi
if [ $INTARNWEB != "0.0.0.0" ]
then
echo 'pass in quick on '$ADSLDEV' proto tcp from any to any port = 80 keep state' >> /etc/ipf.rules
fi
if [ $INTARNSSL != "0.0.0.0" ]
then
echo 'pass in quick on '$ADSLDEV' proto tcp from any to any port = 443 keep state' >> /etc/ipf.rules
fi
if [ $INTARNRTSP != "0.0.0.0" ]
then
echo 'pass in quick on '$ADSLDEV' proto tcp from any to any port = 554 keep state' >> /etc/ipf.rules
echo 'pass in quick on '$ADSLDEV' proto udp from any to any port = 554 keep state' >> /etc/ipf.rules
fi
if [ $INTARNMYSQL != "0.0.0.0" ]
then
echo 'pass in quick on '$ADSLDEV' proto tcp from any to any port = 3306 keep state' >> /etc/ipf.rules
fi
if [ $INTARNJABBER != "0.0.0.0" ]
then
echo 'pass in quick on '$ADSLDEV' proto tcp from any to any port = 5222 keep state' >> /etc/ipf.rules
echo 'pass in quick on '$ADSLDEV' proto tcp from any to any port = 5269 keep state' >> /etc/ipf.rules
fi
echo '' >> /etc/ipf.rules
echo '#阻塞内部网络访问以下指定IP地址' >> /etc/ipf.rules
echo 'block out quick proto tcp/udp from any to any port = 8000 #不能连接QQ ' >> /etc/ipf.rules
echo 'block out quick proto tcp/udp from any to 61.141.194.202 #不能连接QQ ' >> /etc/ipf.rules
echo 'block out quick proto tcp/udp from any to 61.141.194.207 #不能连接QQ' >> /etc/ipf.rules
echo 'block out quick proto tcp/udp from any to 61.141.238.145 #不能连接QQ' >> /etc/ipf.rules
echo 'block out quick proto tcp/udp from any to 61.144.238.146 #不能连接QQ' >> /etc/ipf.rules
echo 'block out quick proto tcp/udp from any to 218.17.209.18 #不能连接QQ' >> /etc/ipf.rules
echo 'block out quick proto tcp/udp from any to 218.17.209.23 #不能连接QQ' >> /etc/ipf.rules
echo 'block out quick proto tcp/udp from any to 219.133.40.15 #不能连接QQ ' >> /etc/ipf.rules
echo 'block out quick proto tcp/udp from any to 202.104.129.242 #不能连接QQ' >> /etc/ipf.rules
echo 'block out quick proto tcp/udp from any to 202.104.129.251 #不能连接QQ' >> /etc/ipf.rules
echo 'block out quick proto tcp/udp from any to 202.104.129.252 #不能连接QQ' >> /etc/ipf.rules
echo 'block out quick proto tcp/udp from any to 202.104.129.254 #不能连接QQ' >> /etc/ipf.rules
echo 'block out quick proto tcp/udp from any to 204.134.15.1 #不能连接QQ' >> /etc/ipf.rules
echo '' >> /etc/ipf.rules
echo '#内部网络可以访问外部网络' >> /etc/ipf.rules
echo 'pass out log on '$ADSLDEV' proto icmp all keep state' >> /etc/ipf.rules
echo 'pass out log on '$ADSLDEV' proto tcp/udp from any to any keep state' >> /etc/ipf.rules
echo '' >> /etc/ipf.rules
echo '#阻塞外部网络的其它请求' >> /etc/ipf.rules
echo 'block return-rst in log on '$ADSLDEV' proto tcp from any to '$ADSLIP' flags S/SA' >> /etc/ipf.rules
echo 'block return-icmp(net-unr) in log on '$ADSLDEV' proto udp from any to '$ADSLIP'' >> /etc/ipf.rules
echo 'block in log on '$ADSLDEV' all' >> /etc/ipf.rules
echo '' >> /etc/ipf.rules
echo '#阻塞内部网络访问以下指定IP地址' >> /etc/ipf.rules
echo '#block in log quick on rl1 proto tcp from any to 202.106.185.77 flags S/SA #不能连接163.com' >> /etc/ipf.rules
echo '' >> /etc/ipf.rules
echo '#内部网络的数据全部可以通过防火墙' >> /etc/ipf.rules
echo 'pass in on '$INTARNDEV' all' >> /etc/ipf.rules
echo 'pass out on '$INTARNDEV' all' >> /etc/ipf.rules
echo 'pass in on lo0 all' >> /etc/ipf.rules
echo 'pass out on lo0 all' >> /etc/ipf.rules
echo '' >> /etc/ipf.rules
echo '#让VPN能通过防火墙' >> /etc/ipf.rules
echo 'pass in quick on '$ADSLDEV' proto tcp from any to any port = 47 keep state' >> /etc/ipf.rules
echo 'pass out quick on '$ADSLDEV' proto tcp from any port = 47 to any keep state' >> /etc/ipf.rules
echo 'pass in quick on '$ADSLDEV' proto tcp from any to any port = 1723 keep state' >> /etc/ipf.rules
echo 'pass out quick on '$ADSLDEV' proto tcp from any port = 1723 to any keep state' >> /etc/ipf.rules
echo 'pass in proto gre from any to any keep state' >> /etc/ipf.rules
echo 'pass out proto gre from any to any keep state' >> /etc/ipf.rules
echo 'pass in on ng0 all' >> /etc/ipf.rules
echo 'pass out on ng0 all' >> /etc/ipf.rules
/sbin/ipf -Fa -f /etc/ipf.rules
/sbin/ipnat -CF -f /etc/ipnat.rules
############################## END ADSLIP.SH #################################
最后我们还要在/etc/rc.conf中加入以下命令行:
gateway_enable="YES"
到这里我们就完成了基于ADSL的VPN防火墙(IPFILTER)网关的安装和配置,至于如何做你的防火墙规则就看你自己了以上只是一个样板而已。
在这里我要谢谢quakelee,我是参考他的"使用FreeBSD配置基于ADSL的VPN网关+防火墙"文章整理出来的,因为我喜欢使用IPFILTER做防火墙。
注:任何转载或摘抄请注明文章出处(中文FreeBSD用户组 http://www.cnfug.org)
作者(译者)信息:
陈永光(Charlin) ,自由软件爱好者。1997年开始学习Linux,1999年开始学习FREEBSD。2000年毕业后一直在深圳市崛计算机网络技术有限公司里负责技术方面的工作,现在已经成功的把FREEBSD应用到INTERNET服务器上和几个校园网解决方案上。你可以通过charlin@88vip.com与他联系。
[此贴子已经被作者于2003-8-14 22:39:40编辑过]
页:
[1]