一次性进群,长期免费索取教程,没有付费教程。
教程列表见微信公众号底部菜单
进微信群回复公众号:微信群;QQ群:16004488
微信公众号:计算机与网络安全
ID:Computer-network
虚拟专用网所使用的网络有什么限制?例如,目前很多的网络运营商,并不允许GRE协议或者是IPSEC协议的数据包通过,因此这时采用PPTP或者是IPSEC就有一定的困难。
是在网关之间建立安全隧道,还是需要客户端先建立虚拟连接拨到服务器。这两者所保护的安全有较大程度的区别。对于前者来说,数据在网关之间传输时是安全的,因此常常用于一些具有分支机构的公司,将各个分支结构通过虚拟专用网统一起来而用。而对于后者来说,则更方便于外部不确定位置的员工访问内部资源时使用。这两者在建设时一个重要的不同点在于,前者对于用户来说是透明的,不需要在用户端做特殊的配置,而后者则不然,需要进行特殊配置,甚至有时需要用户安装特定的软件,这时一般需要考察Windows操作系统所支持VPN的类型。
首先介绍一下Windows 操作系统对VPN的支持情况,Windows 系统中包括三种类型的VPN技术:点对点隧道协议(PPTP)、L2TP以及IPSEC隧道模式。PPTP是在Windows NT 4.0 中引入的,它利用点对点协议(PPP)用户身份验证和Microsoft点对点加密(MPPE)来封装和加密 IP、IPX以及NetBEUI通信。由于有第2版的Microsoft质询握手身份验证协议(MS-CHAP v2)和强密码,PPTP是一种安全的VPN技术。对于不是基于密码的身份验证来说,Windows 系统可用扩展身份验证协议——传输层安全性(EAP-TLS)来支持智能卡。PPTP已受到广泛支持,它易于部署且可跨网络地址转换器(NAT)使用。
第二层隧道协议L2TP利用PPP用户身份验证和IP 安全(IPSEC)加密来封装和加密 IP、IPX以及NetBEUI 通信。这种组合(称为 L2TP/IPSEC)使用基于证书的计算机身份验证来创建安全的和加密的通道(IPSEC安全关联),然后使用基于PPP的用户身份验证来创建L2TP隧道。L2TP/IPSEC为每个数据包都提供数据完整性和数据身份验证。但是,L2TP/IPSEC需要使用公钥基本结构(PKI)来分配计算机证书,且只被Windows 系统 VPN客户端支持。
IPSEC隧道模式在隧道模式下使用封装安全有效负载(ESP)来封装和加密单路广播 IP通信。Windows 系统 IPSEC 隧道模式只用于路由器对路由器 VPN 连接,这是因为当前的IPSEC 标准并未指定用于为远程访问连接提供用户身份验证和地址分配的方法。
如果使用的是L2TP或者是IPSEC,则必须部署 PKI,PKI 可将计算机证书分配给VPN服务器和VPN客户端。虽然 Windows 系统支持许多新的和旧的 PPP身份验证协议,但是PPTP的MPPE加密仍需要使用MS-CHAP、MS-CHAP v2或EAP-TLS。如果没有智能卡,建议使用MS-CHAP v2。尽管由于PPP身份验证过程受IPSEC加密的保护而使L2TP无需特定的身份验证协议,但是仍建议使用MS-CHAP v2和EAP TLS。
安全的VPN连接要求对封装数据进行加密。要确保加密,需要为 VPN 连接创建远程访问策略(NAS端口类型设置为虚拟(VPN)),并清除该策略的配置文件设置的加密选项卡上的不加密复选框。此外,可通过选择或清除基本(对于 PPTP 和 L2TP来说,分别是 40 位MPPE和56位数据加密标准 [DES])、强(对于 PPTP 和 L2TP 来说,分别是56位 MPPE和56位DES)或最强(对于 PPTP 和 L2TP 来说,分别是128位MPPE和3DES),来指定所需的加密级别。最强只能和 Windows 系统 High Encryption Pack 结合使用。
除了Windows操作系统自己支持的VPN之外,还有一些使用自定义协议的VPN解决方案。这方面最著名的就是 OpenVPN。OpenVPN 是一个强大、高度可配置、基于 ssl 的开源VPN软件。它具有多种验证方式以及许多强大的功能。OpenVPN工作在TCP/UDP层,使用SSL/TLS 协议进行网络传输。支持多种客户认证方法,如证书、smart cards,加上用户名密码的证书认证等。除此以外,还有强大的ACL功能限制客户的信息交换。OpenVPN可以运行在多种操作系统中,包括:Linux、Windows 、OpenBSD、FreeBSD、NetBSD、Mac OS X、Solaris。使用OpenVpn,可以实现:
使用特定UDP或TCP端口实现两台主机的之间的VPN连接。
实现C/S结构,实现多台Client通过Server服务器互联互通。
通过TLS/SSL加密保证数据传输的安全。
通过数据的压缩,提高数据传输的速度。
可以从http://openvpn.net/下载最新版本的openvpn 源代码包或者是安装包。
表1 几种VPN解决方案的对比
表1对基于几种常见的技术实现的VPN方案进行了比较。可以看出:
使用PPTPD建立VPN服务器,使用较为方便,能够较好地实现安全与易用性的折衷。服务器可以选择使用Linux或者是BSD系统,不需要安装任何客户端。
使用OpenVPN建立虚拟专用网,可以保证VPN的使用不受ISP防火墙过滤的影响,因此更易用于跨越不受控制的公网或者是上网地点不大确定的情况。
下面我们将分别介绍一下PPTPD和OpenVPN的安装和使用。
一、PPTPD
1、PPTPD的安装过程
以下我们简要介绍一下在Debian Linux系统下面的安装过程。之所以选择Debian系统,是因为与Redhat相比,Debian的软件包管理相当方便,在软件包安装的时候,可以自动解决包之间的依赖性。
在Debian Linux操作系统上面安装PPTPD需要如下步骤:
首先要给VPN服务器的内核添加mppe补丁,从debian获取补丁:
apt-get install kernel-patch-mppe
然后在当前内核对应的源代码目录,执行修补程序,
#cd /usr/src/kernel-source-2.6.8
#/usr/src/kernel-patches/all/apply/mppe
在内核的ppp下,会多一个 mppe功能,把它编译成模块的形式,并安装,模块形式可以直接挂载,不用启动机器,修改/etc/modules,添加一行ppp_mppe就可以了。用以下命令检查内核MPPE补丁是否安装成功:
#modprobe ppp-compress-18
然后就可以安装PPTP服务程序和配置程序了。
apt-get install pptpd webmin-pptp-server
下面就可以直接进webmin对PPTPD进行设置了。一切按默认设置,要把[Enable MPPE encryption]选项设置为[Must be used],这样,就不用修改win客户端的安全默认设置了。用以下命令检查PPP是否支持MPPE:
#strings '/usr/sbin/pppd' grep -i mppe wc --lines
2、PPTPD的配置
PPTPD的配置文件主要有如下几个:/etc/pptpd.conf是PPPTPD的配置文件,options.pptpd是PPTPD的配置文件,而/etc/ppp/chap-secrets则是用户的用户名/密码文件。
首先看/etc/pptpd.conf,下面是一个样本配置文件:
debug
option /etc/ppp/options.pptpd
localip 192.168.0.254 #本地VPN服务器的IP
remoteip 192.168.1.1-254 #客户端被分配的IP范围
其次是options.pptpd,下面是一个样本配置文件。
auth
lock
debug
proxyarp
lock
name rh9vpn #VPN服务器的名字
multilink
refuse-pap
refuse-chap
refuse-mschap
refuse-eap
refuse-mschap-v2
require-mppe
ms-wins 192.168.1.2 #把想要在网络邻居中看到的机器的IP填写到这里
ms-dns 192.168.1.2 #DNS服务器地址
dump
logfile /var/log/pptpd.log #日志存放的路径
最后是/etc/ppp/chap-secrets,这个文件中将要以明文的方式配置可以使用这个VPN的用户及其密码。
# client server secret IP addresses
"test@gd.cn" * "test" *
因为密码是明文显示的,最好能修改文件权限,使root作为owner和chmod 700。上面第二行代码的四项内容分别对应第一行中的四项。“test@gd.cn”是Client端的VPN用户名;“server”对应的是 VPN 服务器的名字,该名字必须和/etc/ppp/options.pptpd 文件中指明的一样,或者设置成“*”号来表示自动识别服务器;“secret”对应的是登录密码;“IP addresses”对应的是可以拨入的客户端IP地址,如果不需要做特别限制,可以将其设置为“*”号。
然后就可以设置IP伪装转发了,这样通过VPN连接上来的远程计算机才能互相ping通,实现像局域网那样的共享。用下面的命令进行设置:
#echo 1 >/proc/sys/net/ipv4/ip_forward
可以将这条命令放到文件/etc/rc.d/rc.local里面,以实现每次开机时自动运行该命令。
然后配置Linux服务器的防火墙,将1723端口和47端口打开,并打开GRE协议。
#/sbin/iptables -A INPUT -p tcp --dport 1723 -j ACCEPT
#/sbin/iptables -A INPUT -p tcp --dport 47 -j ACCEPT
#/sbin/iptables -A INPUT -p gre -j ACCEPT
到这里Linux服务器的设置就完成了,下面将利用Windows客户端进行测试。
3、客户端配置
打开“控制面板”->“网络连接”->“新建连接”,在弹出的“网络连接向导”窗口中,点击“下一步”。
在下一个页面选择“通过Internet连接到专用网络”,点击“下一步”。
输入VPN主机名(可以是IP地址或者域名),点击“下一步”。
创建此连接,选择“所有用户使用此连接”,点击“下一步”。
输入连接名称,如“VPN”,点击“完成”。
这时会生成一个名为“VPN”的新连接,点击这个图标,会弹出登录窗口,输入账号密码后登录即可。
4、常见问题
(1)在认证通过后,所有的网络流量均从VPN服务器发出,有的时候希望只是在访问某些地址的时候通过VPN服务器,缺省仍然是通过本机,这时候需要:
①打开网络连接,右键选择VPN连接、属性、网络,选择“Internet 协议”,属性、高级、常规,不选中“在远程网络上使用默认网关”即可。
②设置希望通过VPN服务器访问IP地址的路由:在Windows命令行下面输入:route ADD 要访问的网络,MASK 该网络的掩码,VPN 连接得到的地址。VPN 连接的地址可以通过ipconfig 得到。例如,VPN服务器的地址为202.38.120.250,连接成功后,通过ipconfig看到本地得到的地址为192.168.0.3,希望访问8网段的服务器时通过VPN访问,则可以:route add 166.111.8.0 255.255.255.0 192.168.0.3。
(2)上网的时候,发现开始正常,到了在网上注册计算机这一步的时候,出现错误734,PPP协议异常终止的错误,这有可能是因为防火墙的问题,请检查客户端是否部署了防火墙,该防火墙是否允许GRE协议。
(3)使用Windows 系统连接VPN成功后,在传输“大块”数据时会出现数据堵塞,导致数据传输失败。这是由于 Windows 系统的一个Bug造成的。根据 TCP/IP协议,在建立 TCP连接时,传输双方都要指明自己的 mss(最大报文长度)大小,然后选取双方之中最小的那个mss,以避免在随后的数据传送过程中出现数据包分片传输的情况。然而Windows 系统并没有这样做,因此导致发送大的数据包的同时,如果数据包标志为不能分段,就会被丢弃。解决方法很简单,就是借助iptalbes,设定主机B进行协商时提出的mss为1356。即在iptables里面加入一条规则:
/sbin/iptables -A FORWARD -p tcp --syn -s 10.100.0.203 -j TCPMSS --set-mss 1356
因为mss是在TCP连接建立开始时,通过带有syn标志的IP数据包进行传输的,所以我们在iptables里面规定,在转发数据时,只要发现带有 syn标志并且源地址为主机B的IP数据包时,将其mss设定为1356字节,这样就与ppp0接口的路径MTU相匹配了。
二、OpenVPN
1、OpenVPN 的安装
首先,Kernel必须支持TUN/TAP设备。
Universal TUN/TAP device driver support
确认Kernel支持TUN/TAP后,可以下载OpenVPN编译并安装。从http://www.openvpn.se(http://www.openvpn.se/)下载安装包安装。安装完成后,在/etc/vpn 目录下,执行openvpn --daemon --config server.conf即可。OpenVPN带一个GUI小工具,会装在系统托盘里,点菜单里的 connect 即可。
2、OpenVPN Server端的配置
只说明在 Linux 下的配置。Windows 下的配置也类似。创建 /etc/vpn/server.conf,内容如下:
port 1494
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh1024.pem
server 10.1.0.0 255.255.255.0
push "route 10.1.0.0 255.255.255.0"
push "route 10.1.1.0 255.255.255.0"
client-config-dir /etc/vpn/ccd
route 10.1.1.0 255.255.255.0
client-to-client //让不同的client之间可以互相“看到”。
keepalive 10 120 //每10秒ping一次,如果120秒没有回应则认为对方已经down。
user nobody
group nobody
persist-key
persist-tun
log-append openvpn.log
verb 3
其中ca.crt,server.key,server.crt可以用OpenSSL创建,dh1024.pem用OpenVPN自带的工具创建。这个配置文件创建了两个网段:10.1.0.*和10.1.1.*,VPN服务器将从这两个网段中给Client分配IP地址。VPN Server自身IP 将是10.0.0.1。“client-config-dir”指明Client 的专有配置文件目录。在这个目录下可以针对特定用户建立配置文件。例如,要为用户abc指定一个 IP 地址(如 10.1.1.5)而不是让 VPN Server 自动分配,可以在配置目录/etc/vpn/ccd下建立一个abc文件,内容如下:
ifconfig-push 10.1.1.5 10.1.1.6
那么VPN Server 就会自动给abc用户分配10.1.1.5 这个地址。注意第一个IP地址的最后一个数字(这里是5)必须是4´n+1 的数。问题是,VPN Server 怎么知道哪个用户是abc呢?它是Client数字证书中的Common Name 域来判断的。就是说,在连接协商时如果Client 端数字证书的Common Name是abc,那么VPN Server就找配置目录下abc这个文件。
对于客户端,从Server中生成ca.crt ,win.crt,win.key文件并拷贝到Windows上。在命令行运行:
openvpn --config win.ovpn
如果要将openvpn做成服务,运行:
openvpnsev.exe -install
这样就可以在服务中找到openvpn服务了。
当openvpn作为服务时,会到config文件夹寻找ovpn后缀的配置文件。生成的日志会放在log文件夹中。在 Client 机器上OpenVPN安装目录的config目录下建立如下client.ovpn文件:
client
dev tun //使用tunnel的模块
proto udp
remote vpn_server_ip 1494
ca ca.crt
cryptoapicert "SUBJ: abc"
nobind
persist-key
persist-tun
verb 3 //设置日志要记录的级别。3 只记录错误信息。4 能记录普通的信息。5 和 6 在连接出现问题时能帮助调试,9是极端的,所有信息都会显示,甚至连包头等信息都显示(像tcpdump)
mute 20 //相同信息的数量,如果连续出现20条相同的信息,将不记录到日志中。
修改remote 一行填上对应VPN Server 的IP和端口。ca.crt 和服务端ca.crt一样,必须把这个ca.crt也放在config目录下。
关键是cryptoapicert "SUBJ: abc" 这行。这一行指定客户端的数字证书从Windows证书Store 里取。在IE的“选项→内容→证书”页面能看到用户的个人数字证书。SUBJ:abc指明选择证书主题中含有 abc 的证书。客户端数字证书也可以用以前贴的 ca 工具生成,如果要给用户abc签发数字证书,只用指明Common Name 是abc即可,然后把生成的abc.p12传给abc用户并告诉导入口令。abc导入这个数字证书后,VPN Client就可以工作了。
3、其他配置
(1)控制运行中的openvpn进程
在配置文件中加入writepid参数指定pid文件。
SIGUSR1——以非root的身份重启openvpn进程。
SIGHUP——重启。
SIGUSR2——输出连接统计到log文件。
SIGTERM,SIGINT——exit。
(2)通过User/Pass登录VPN
首先需要建立/etc/pam.d/openvpn文件如下:
auth required pam_pwdfile.so pwdfile /etc/openvpn/passwd_vpn
account required pam_permit.so
这样就可以使用/etc/ openvpn/passwd_vpn文件来存储用户名/密码了。
public:$1$1reO.OK/$lqn O7k5i4pztKWlU3.
这一行中用户名为public,密码加密后在:之后。可以使用如下的脚本来得到这样的输出:
#! /usr/bin/perl -w
use strict;
# filter "user:cleartext" lines into "user:md5_crypted"
# probably requires glibc
while (<>) {
chomp;
(my $user, my $pass)=split /:/, $_, 2;
my $crypt=crypt $pass, '$1$' . gensalt(8);
print "$user:$crypt\n";
}
sub gensalt {
my $count=shift;
my @salt=('.', '/', 0 .. 9, 'A' .. 'Z', 'a' .. 'z');
my $s;
$s .=$salt[rand @salt] for (1 .. $count);
return $s;
}
微信公众号:计算机与网络安全
ID:Computer-network