如何设置“虚拟私有网路(VPN)” <author> 作者: Arpad Magosanyi <mag@bunuel.tii.matav.hu><newline> 译者: 蒋大伟 <dawei@sinica.edu.tw> <date> v0.2, 7 August 1997 翻译完成日期: 20 Feb 1999 <abstract> 如何建立虚拟私有网路(Virtual Private Network)。 </abstract> <sect>更正 <p> 'no controlling tty problem' -> -o 'BatchMode yes' 是由 Zot O'Connor <zot@crl.com> 所更正。 核心 2.0.30 的警告讯息,是由 mag 所更正。 <sect>推荐广告 <p> 这份文件是 Linux VPN howto,它收集了如何在 Linux (以及一般的 UNIX) 上建立 一个虚拟保护式网路的相关资讯。 <sect1>版权声明 <p> 这份文件是 Linux HOWTO 计划的一部分。它的版权声明如下:除非特别说明,Linux HOWTO 文件的版权归属他们各自的作者所有。Linux HOWTO 文件的全部或部分,可以 使用任何物理或电子形式的媒体来复制与散布,只要这个版权声明被保留在每份拷贝 中。商业行为的再散布是被允许而且受欢迎的;但是,任何的散布行为作者都希望能 被告知。所有翻译、衍生的工作、或合并任何 Linux HOWTO 文件的聚集工作,都必须 受到这个版权声明的保护。也就是说,你不可以从 HOWTO 衍生出一份文件,然後对这 份衍生文件的散布强加上其他限制条件。除非在一些特定的状况下,才会允诺这些限制 条件;请联络 Linux HOWTO 的协调人,他的地址如下。简而言之,我们希望能够尽可 能透过各种管道,来推动这个资讯的散布工作。然而,我们也希望保留 HOWTO 文件的 版权,以及如果有任何对 HOWTOs 的再散布计划也希望能够被通知到。如果有任何疑问 ,请联络 Linux HOWTO 协调人 Tim Bynum,他的电子邮件地址是 linux-howto@sunsite.unc.edu 。 <sect1>免责声明 <p> 一如往常:本文对你所造成的任何危害,作者一概不负责任。正确的条文,请参阅 GNU GPL 0.1.1 的相关部分。 <p> <sect1>郑重声明 <p> 我们所面临的是安全性的问题:如果你没有形成一个好的安全策略,以及做好相关的配套 措施,你将无法获得真正的安全。 <sect1>功劳 <p> 感谢所有提供工具程式给本文使用的人仕。 感谢 Zot O'Connor <zot@crl.com> 不仅指正“no controlling tty”的问题,而且 还提供了解决方法。 <sect1>本文的现况 <p> 在阅读本文前,你应该已具备完整的 IP 管理知识,至少要对“防火墙(firewall)”、ppp 、和 ssh ,等知识,有一些了解。如果你要设定一个 VPN 环境,无论如何一定得知道这些 东西。我只是将我的经验写下来 ,以免日後忘记相关的内容。所以,我相信一定会有安全 的漏洞存在。为了清楚起见,我试著以主机设置为路由器方式,而不是以防火墙的方式,来 说明整个内容,希望大家轻轻松松就能够了解本文。 <sect1>相关文件 <p> <itemize> <item>档案 /usr/doc/HOWTO/Firewall-HOWTO 上的 Linux Firewall-HOWTO 文件 <item>档案 /usr/doc/HOWTO/PPP-HOWTO.gz 上的 Linux PPP-HOWTO 文件 <item>目录 /usr/doc/ssh/* 中的 ssh 文件 <item>Linux “网路管理指引(Network Admins' Guide)” <item>国家标准及技术委员会 (National Institute Standards and Technology,简写为 NIST) 在电脑安全方面的出版品,请参考网址 http://csrc.ncsl.nist.gov/nistpubs/ <item>“防火墙通信论坛(Firewall list)” (majordomo@greatcircle.com) </itemize> <sect>介绍 <p> 由於网路安全问题日益受到重视,所以,防火墙的技术越来越广泛地被应用在,网际网路 和“公司内部网路(intranet)”上,防火墙能力的优劣,对 VPN 的安全性有著举足轻重的 影响。这只是我个人的体会。欢迎大家提出自己的看法。 <sect1>命名惯例 <p> 我将会使用到“主防火墙(master firewall)”和“次防火墙(slave firewall)”这两个专 有名称,然而,VPN 的建置与主仆式架构之间没有任何关联性。我只是把它们看成,两端在 建立连线时,它是个主动的参与者或被动的参与者。发起建立连线的主机,会被当作主防火 墙;然而,被动的参与者,就会被当作次防火墙。 <sect>开始建置 <p> <sect1>规划 <p> 在你开始设定系统前,你应该要先了解一下网路连接的细节。现在,我假定你有两个防火墙 ,各保护一个公司内部网路。所以,现在每个防火墙应该会有两个网路界面(至少)。拿一 张纸,写下它们的 IP 位址和网路遮罩。每个 VPN 的防火墙,将会使用到数个 IP 位址区 段。这些 IP 位址区段,应该设定在你公司现有的子网路的□围以外。我建议使用“私有” IP 位址区段的□围。如下所示: <itemize> <item>10.0.0.0 - 10.255.255.255 <item>172.16.0.0 - 172.31.255.255 <item>192.168.0.0 - 192.168.255.255 </itemize> 为了说明,此处我举了一个设定的案例:有两台 bastion [译注] 主机,分别被称为 fellini 和 polanski。它们各有一个界面连接网际网路 (-out),一个界面连接公司内部网路 (-in) ,以及,一个界面连接 VPN (-vpn)。所有的 IP 位址和网路遮罩,如下: <itemize> <item>fellini-out: 193.6.34.12 255.255.255.0 <item>fellini-in: 193.6.35.12 255.255.255.0 <item>fellini-vpn: 192.168.0.1 点对点 <item>polanski-out: 193.6.36.12 255.255.255.0 <item>polanski-in: 193.6.37.12 255.255.255.0 <item>polanski-vpn: 192.168.0.2 点对点 </itemize> 译注: bastion 是指暴露在公司网路外部的防火墙闸道。 所以我们有个计划。 <sect1>搜集工具 <p> 你将会需要 <itemize> <item>Linux 防火墙 <item>核心 <item>非常少的设定 <item>ipfwadm 程式 <item>fwtk 程式 <item>VPN 所使用的工具 <item>ssh 程式 <item>pppd 程式 <item>sudo 程式 <item>pty-redir 程式 </itemize> 目前使用的版本: <itemize> <item>核心: 2.0.29 。请使用稳定的核心,而且,必须比 2.0.20 还新,因为 ping'o'death 的错误。在撰写本文时,最後一个稳定的核心是版本 2.0.30,但是它有一些错误。如果 ,你想要使用最新版核心所提供,既快又酷的网路程式码,你自己可以尝试看看,版本 2.0.30 对我而言,已经很好用了。 <item>基本的作业系统:我比较喜欢 Debian 所发行的版本。你绝对使用不到任何大型的 软体套件,当然,也包含 sendmail 在内。你也绝对不能像其它的 UNIX 主机一样,允许 telnet、ftp、和 'r' 命令,等功能的使用。 <item>ipfwadm 程式: 我使用的是 2.3.0。 <item>fwtk 程式: 我使用的是 1.3。 <item>ssh 程式: >= 1.2.20。较旧的版本,下层的协定会有问题。 <item>pppd 程式: 我测试的是 2.2.0f,但是我无法确定它是否安全,这就是为什麽我会 将它的 setuid 位元拿掉,并透过 sudo 来执行它的原因。 <item>sudo 程式: 我所知道的最新版本是 1.5.2。 <item>pty-redir 程式: 这是我写。请至 ftp://ftp.vein.hu/ssa/contrib/mag/pty-redir-0.1.tar.gz 取得。现在的版本是 0.1 。如果使用上有任何问题,请来信告知。 </itemize> <sect1>编译与安装 <p> 你现在的工作不是编译就是安装所搜集到的工具。 并参阅其(以及 firewall-howto) 详细的说明文件。现在,我们已经安装好这些工具了。 <sect1>其它子系统的设定 <p> 设定防火墙以及其它的项目。你必须在两台防火墙主机之间,允许 ssh 资料的流通。这 是指,主防火墙会有网路连线到次防火墙的埠 22。在次防火墙上启动 sshd,来验证是否 允许你“登入(login)”。这个步骤尚未测试过,请告诉我你的测试结果。 <sect1>设定 VPN 的使用者帐户 <p> 以你日常使用的工具(例如,vi、mkdir、chown、chmod)在次防火墙上建立一个使用者帐 户,你也可以在主防火墙上建立一个使用者帐户,但是,我认为在开机阶段设定连线就可以 了,所以,使用原始的 root 帐户就已足够。有任何人可以为我们说明一下,在主防火墙上 使用 root 帐户,会有什麽危险性? <sect1>为 master 帐户,产生一个 ssh key <p> 你可以使用 ssh-keygen 程式。如果,你要自动设置 VPN,你可以设定一个没有密码的 “私人钥匙(private key)”。 <sect1>为 slave 帐户,设置自动的 ssh 登入环境。 <p> 在次防火墙中,复制你刚才产生的“公共钥匙(public key)”到,使用者帐户 slave 中 的 .ssh/authorized_keys 档案里,并且,设定档案的使用权限,如下: <verb> drwx------ 2 slave slave 1024 Apr 7 23:49 ./ drwx------ 4 slave slave 1024 Apr 24 14:05 ../ -rwx------ 1 slave slave 328 Apr 7 03:04 authorized_keys -rw------- 1 slave slave 660 Apr 14 15:23 known_hosts -rw------- 1 slave slave 512 Apr 21 10:03 random_seed </verb> 其中,第一行是 ˜slave/.ssh,第二行是 ˜slave。 <sect1>加强 ssh 在 bastion 主机上的安全性。 <p> 请按照我在 sshd_conf 上的设定: <verb> PermitRootLogin no IgnoreRhosts yes StrictModes yes QuietMode no FascistLogging yes KeepAlive yes RhostsAuthentication no RhostsRSAAuthentication no RSAAuthentication yes PasswordAuthentication no PermitEmptyPasswords no </verb> 密码认证(PasswordAuthentication)被关闭了,所以,你只有使用授权过的 key,才能够 完成登入的动作。(当然,你也已经关闭了,telnet 与 'r' 命令)。 <sect1>允许 ppp 的执行,和这两个帐户的路由。 <p> 当你的 master 帐户是 root 时(以我的例子而言),你不必做任何事情。至於 slave 帐户,则会在你的 /etc/sudoers 的档案中出现一行: <verb> Cmnd_Alias VPN=/usr/sbin/pppd,/usr/local/vpn/route slave ALL=NOPASSWD: VPN </verb> 正如你所看到的,我在次防火墙主机上,使用了一些命令稿(scripts),来设定 ppp 和路由表。 <sect1>撰写命令稿程式 <p> 在主防火墙主机上,我使用了一个成熟的启始命令稿: <verb> #! /bin/sh # 程式架构 这个档案是个建立在 /etc/init.d/ 目录下的命令稿实例。 # 你应该在 /etc/init.d 目录下使用这个命令稿。 # # 作者 Miquel van Smoorenburg <miquels@cistron.nl>. # Debian GNU/Linux 修订版作者 # Ian Murdock <imurdock@gnu.ai.mit.edu>. # # 版本: @(#)skeleton 1.6 11-Nov-1996 miquels@cistron.nl # PATH=/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/bin/X11/: PPPAPP=/home/slave/ppp ROUTEAPP=/home/slave/route PPPD=/usr/sbin/pppd NAME=VPN REDIR=/usr/local/bin/pty-redir SSH=/usr/bin/ssh MYPPPIP=192.168.0.1 TARGETIP=192.168.0.2 TARGETNET=193.6.37.0 MYNET=193.6.35.0 SLAVEWALL=polanski-out SLAVEACC=slave test -f $PPPD || exit 0 set -e case "$1" in start) echo setting up vpn $REDIR $SSH -o 'Batchmode yes' -t -l $SLAVEACC $SLAVEWALL sudo $PPPAPP >/tmp/device TTYNAME=`cat /tmp/device` echo tty is $TTYNAME sleep 10s if [ ! -z $TTYNAME ] then $PPPD $TTYNAME ${MYPPPIP}:${TARGETIP} else echo FAILED! logger "vpn setup failed" fi sleep 5s route add -net $TARGETNET gw $TARGETIP $SSH -o 'Batchmode yes' -l $SLAVEACC $SLAVEWALL sudo $ROUTEAPP ;; stop) ps -ax | grep "ssh -t -l $SLAVEACC " | grep -v grep | awk '{print $1}' | xargs kill ;; *) # echo "Usage: /etc/init.d/$NAME {start|stop|reload}" echo "Usage: /etc/init.d/$NAME {start|stop}" exit 1 ;; esac exit 0 </verb> slave 帐户可以使用命令稿来设定路由 (/usr/local/vpn/route): <verb> #!/bin/bash /sbin/route add -net 193.6.35.0 gw 192.168.0.1 </verb> 而其 .ppprc 的内容,如下: <verb> passive </verb> <sect>让我们检视执行的结果: <p> master 会登入到 slave 帐户里、启动 pppd、以及,将所有的资料重导至本机的 pty( 虚拟终端机)。整个执行流程如下: <itemize> <item>配置一个新的 pty <item>透过 ssh 登入 slave 帐户 <item>在 slave 帐户中执行 pppd <item>master 在本机的 pty 执行 pppd <item>并且在用户端设定路由表。 </itemize> 此处我们考虑到了时序的问题(不是太严格的要求),这就是为什麽我们会使用到 'sleep 10s' 这个叙述的原因。 <sect>著手执行。 <p> <sect1>登入 <p> 现在,你应该已经测试过 ssh 是否能够正常地工作。如果,slave 拒绝你登入,请阅读 记录档。也许是档案使用权限或 sshd ,在设定上的问题。 <sect1>启动 ppp <p> 登入到 slave 帐户,并执行: <verb>sudo /usr/sbin/pppd passive </verb> 此时,如果工作正常你应该会看到一些乱码。假设,没有出现乱码,不是 sudo 就是 pppd 有问题。请参考,记录档、<em>/etc/ppp/options</em> 、和 <em>.ppprc </em>,等档案 ,以便找出是那个命令出了问题。问题排除後,将 'passive' 这个字写到 .ppprc 里,然 後再试一次。以压下 enter、'˜'、和 '^Z'等按键的方式,清除萤幕上的乱码,继续 工作。现在,你应该会看到 master 的“输入提示符号(prompt)”,然後执行 kill %1 。如果你想知道更多有关“逸出字元(escape character)”的说明,请参阅“调整(tuning)” 那一节。 <sect1>一次完成两个动作 <p> 当然,你也可以这麽做 <verb>ssh -l slave polanski sudo /usr/sbin/pppd </verb> 如果工作正常,它就会当著你的面,传送一些看似乱码的资料。 <sect1>Pty 的重导功能 <p> 这次,我们试著重导上面的动作: <verb>/usr/local/bin/pty-redir /usr/bin/ssh -l slave polanski sudo /usr/sbin/pppd </verb> 好长的句子,不是吗?你应该使用 ssh 执行档的完全路径名称,为了安全的理由,pty-redir 程式只允许你使用这种方式。现在,你会透过这个程式取得一个装置名称。假设,你取得的 是 <em>/dev/ttyp0 </em> 。你可以使用 ps 命令来检视目前的状况。请找寻 'p0' 这个装 置的相关叙述。 <sect1>这个装置上面,会有些什麽东西? <p> 试著执行 <verb>/usr/sbin/pppd /dev/ttyp0 local 192.168.0.1:192.168.0.2 </verb> 来建立连线。然後,检视 ifconfig 命令的输出结果,看是否已经建立了这个装置,然後 ,使用 ping 来检查你的虚拟网路。 <sect1>设定路由 <p> 除了设定主防火墙主机的路由,次防火墙主机也要设定。现在,你应该能够从公司的一个 内部网路上的主机,ping 到其它内部网路上的主机。接著,设定额外的防火墙规则。现 在,你已经拥有了 VPN 的环境,你可以设定公司两个内部网路之间的连接规则。 <sect>调整 <p> <sect1>设定的调整 <p> 正如我所说的,这份文件只是我个人设定 VPN 的备忘录而已。设定中有部分的内容,我还 未测试过。等到我测试过後,会给它们正确的定位,或有任何人告诉我“它是如何工作的” 。有个最重要的事情大家必须铭记在心,ppp 网路连线尚未使用 8-bit。我自己也觉得 ssh 或 pty 的设定,一定还有要加强的地方。在 ssh 的设定中,使用了“颚化符号(tilde)” (˜) 字元做为逸出字元。它可以停止或减缓两端之间的通讯,当任何的“新行符号- 颚化符号(newline-tilde)”逸出顺序的出现,会使得 ssh 跳到输入提示符号的模式。ssh 的文件上说: < 在大部分的系统上,若设定不使用逸出字元,则就算是你使用了 tty ,也会造成通讯对话的透通化。> 这个功能相对於 ssh 的选项标记是 '<em>-e</em>' ,你也可以在设定档中设定它。 <sect1>频宽与安全谁重要 <p> 不论建置任何的虚拟网路,都会浪费掉实际资源。VPN 会吃掉频宽和计算的资源。你的目标 应该是如何取得双赢的局面。你可以使用 '-C' 开关或 'CompressionLevel' 选项,来调整 它。你也以尝试使用另一种加密法,但是,我并不建议这麽做。也请注意,如果你使用越高 的压缩等级,你传送资料的来回时间就越长。欢迎提供任何相关的测试报告。 <sect>分析易受攻击的弱点 <p> 我试著在此处说明一下,这个特别的设定和 VPNs 一般有那些易受攻击的弱点。热诚地欢迎 各位发表任何意见。 <itemize> <item>sudo 程式:我承认,我过度地使用了 sudo。我深信目前它仍然比使用 setuid bits 还安全。Linux 上仍然没有好的存取控制机制,是个不争的事实。只有等到相容 POSIX.6 标准的核心正式发行了< http://www.xarius.demon.co.uk/software/posix6/>。更 糟糕的是,我居然透过 sudo 来呼叫执行 shell 的命令稿程式。实在糟糕透了。你有任何 建议麽? <item>pppd 程式:它也会使用 suid root (译注) 的执行方式。你可以透过使用者的 .ppprc 来设定它。留心,它可能会有“缓冲区超限运转(buffer overrun)”的状况发生。底限是 :尽可能地保护你的 slave 帐户的安全性。 <item>ssh 程式:当心,ssh 在 1.2.20 以前的版本有安全的漏洞。更糟糕的是,我们的 设定是,当我们对 master 帐户的安全性做出了让步,相对地,也弃守了 slave 帐户的安 全底限,而且,我们使用了两个透过 sudo 启动的程式,也大开了攻击之门。那是因为,为 了能够自动设定 VPN,我们选择让 master 使用没有密码的“私人钥匙(secret key)”。 <item>firewall 程式: bastion 主机上的防火墙,若规则设定的不恰当,就等於是大开公 司内部网路的方便之门。我建议大家使用 IP“伪装(Masquerading)”的技术(此时,就算是 路由设定不正确,所造成的影响也是微不足道的),以及,在 VPN 的界面上做严格的控制 。 </itemize> 译注: suid root 是指任何执行该程式的人,在执行的当时会取得 root 的权限。其中,suid( 设定使用者识别代码)是指设定档案属性的第 11 个位元,让执行该档案的人,成为档案的 拥有者。 </article>