这是本文档旧的修订版!
目录
OpenVPN的简单配置
VPN是Virtual Private Network(虚拟专用网络)的缩写,是在公共网络上通过隧道和加密技术创建专用(私有)网络的技术。OpenVPN是基于SSL/TLS标准协议的一种VPN实现方案。
本文以用KVM虚拟机模拟网络环境中的网络拓扑结构为例,讲述一个简单的OpenVPN配置过程。
在这个例子中,home网络和away网络是同一个机构下的两个异地网络,为了让两地的内网用户能安全的互访,需要在两者之间搭建一条VPN通道。为此,slk-home-gate除了作为home网络的网关外,同时兼任OpenVPN Server;slk-away-gate网关则作为OpenVPN Client。此外,对于出差的用户,也能在外网通过授权证书作为OpenVPN Client接入到VPN中。
操作系统基于slackware64 14.0。
构建PKI
首先构建我们自己的公钥基础设施PKI(Public Key Infrastructure)。在这里,我们将为OpenVPN Server和每个OpenVPN Client生成一对证书(Certificate,也叫公钥Public Key)和私钥(Private Key);同时生成一对主CA(Master Certificate Authority)用的证书和私钥,用于对OpenVPN Server和Client的证书进行签字。
easy-rsa工具包
OpenVPN提供了一个easy-rsa工具包,方便构建PKI。这里使用2.0版本,首先复制一份:
# cd /usr/doc/openvpn-2.2.2/easy-rsa # cp -r 2.0 /root/easy-rsa # cd /root/easy-rsa
接下来的工作都在/root/easy-rsa目录下进行。
vars配置文件
编辑vars配置文件,进行一些设置。主要的设置地方有:
- KEY_CONFIG,指定openssl版本,一般由whichopensslcnf脚本自动判断;
- KEY_DIR,生成的密钥存放目录,缺省为当前目录下的keys子目录;
- KEY_SIZE,指定密钥长度,缺省为1024,如果用于生产环境,建议提高到2048;
- KEY_COUNTRY、KEY_PROVINCE、KEY_CITY等放在证书中的信息。
这里我们仅设置一些信息字段(数据是虚构的):
export KEY_COUNTRY="CN" export KEY_PROVINCE="Yunnan" export KEY_CITY="Kunming" export KEY_ORG="Yunnan University" export KEY_EMAIL="admin@copyleft.org" export KEY_NAME="OpenVPN" export KEY_OU="Information School"
不设置KEY_CN(指定Common Name),因为后续操作中这些信息会用到多次,但每次的Common Name都不一样。
应用配置:
# . ./vars
清理
开始生成新的密钥之前,先做一次清理工作:
# ./clean-all
生成CA的证书和私钥
生成主CA的证书和私钥,在Common Name的地方输入slk-home-ca:
# ./build-ca
为了方便理解执行过程,这里同时附上输出信息:
Generating a 1024 bit RSA private key .....................................++++++ ....++++++ writing new private key to 'ca.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [CN]: State or Province Name (full name) [Yunnan]: Locality Name (eg, city) [Kunming]: Organization Name (eg, company) [Yunnan University]: Organizational Unit Name (eg, section) [Information School]: Common Name (eg, your name or your server's hostname) [changeme]:slk-home-ca Name [OpenVPN]: Email Address [admin@copyleft.org]:
生成Server的证书和私钥
生成OpenVPN Server的证书和私钥,Common Name设为slk-home-gate:
# ./build-key-server slk-home-gate
输出信息:
Generating a 1024 bit RSA private key ........++++++ ...........++++++ writing new private key to 'slk-home-gate.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [CN]: State or Province Name (full name) [Yunnan]: Locality Name (eg, city) [Kunming]: Organization Name (eg, company) [Yunnan University]: Organizational Unit Name (eg, section) [Information School]: Common Name (eg, your name or your server's hostname) [slk-home-gate]: Name [OpenVPN]: Email Address [admin@copyleft.org]: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Using configuration from /root/easy-rsa/openssl-1.0.0.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName :PRINTABLE:'CN' stateOrProvinceName :PRINTABLE:'Yunnan' localityName :PRINTABLE:'Kunming' organizationName :PRINTABLE:'Yunnan University' organizationalUnitName:PRINTABLE:'Information School' commonName :PRINTABLE:'slk-home-gate' name :PRINTABLE:'OpenVPN' emailAddress :IA5STRING:'admin@copyleft.org' Certificate is to be certified until Nov 11 22:30:55 2022 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
生成Client的证书和私钥
生成OpenVPN Client的证书和私钥。首先为slk-away-gate生成,Common Name也设为slk-home-gate:
# ./build-key slk-away-gate
输出信息:
Generating a 1024 bit RSA private key ..................++++++ .................++++++ writing new private key to 'slk-away-gate.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [CN]: State or Province Name (full name) [Yunnan]: Locality Name (eg, city) [Kunming]: Organization Name (eg, company) [Yunnan University]: Organizational Unit Name (eg, section) [Information School]: Common Name (eg, your name or your server's hostname) [slk-away-gate]: Name [OpenVPN]: Email Address [admin@copyleft.org]: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Using configuration from /root/easy-rsa/openssl-1.0.0.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName :PRINTABLE:'CN' stateOrProvinceName :PRINTABLE:'Yunnan' localityName :PRINTABLE:'Kunming' organizationName :PRINTABLE:'Yunnan University' organizationalUnitName:PRINTABLE:'Information School' commonName :PRINTABLE:'slk-away-gate' name :PRINTABLE:'OpenVPN' emailAddress :IA5STRING:'admin@copyleft.org' Certificate is to be certified until Nov 11 22:37:11 2022 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
为其他OpenVPN Client生成证书和私钥,可以有多份:
# ./build-key slk-home-client2 # ./build-key slk-home-client3 ...
生成Diffie Hellman参数
生成Diffie Hellman parameters,在OpenVPN Server上会用到:
# ./build-dh
密钥派发
至此,所有的证书和私钥都生成完毕,后续就可以派发到相应的机器上。PKI所在的机器原理上是独立的,不需要和OpenVPN Server或Client在同一台机器上。
在派发密钥时,私钥(后缀为.key)必须通过一个安全的秘密通道进行,证书(后缀为.crt)和Diffie Hellman参数则不必。
OpenVPN Server配置
获得密钥
从PKI获得CA证书、Server证书和私钥、DH参数,并放到相应位置:
- ca.crt → /etc/openvpn/certs/
- slk-home-gate.crt → /etc/openvpn/certs/
- slk-home-gate.key → /etc/openvpn/keys/
- dh1024.pem → /etc/openvpn/
复制配置文件
先复制一份OpenVPN提供的配置样例,再做修改:
# cd /etc/openvpn/ # cp /usr/doc/openvpn-2.2.2/sample-config-files/server.conf .
接下来编辑server.conf进行设置,我们将配置一个routed模式的OpenVPN。
设置密钥
首先设置各个密钥信息:
ca certs/ca.crt cert certs/slk-home-gate.crt key keys/slk-home-gate.key # This file should be kept secret dh dh1024.pem
设置虚拟网络地址
指定VPN将要使用的虚拟网络地址范围:
server 10.10.40.0 255.255.255.0
OpenVPN Server将自动使用10.10.40.1这个地址。
至此,就配好了一个最基本的OpenVPN Server,可以与OpenVPN Clients建立点对点的VPN连接了。
当然,这样的功能远远不够,下面继续。
加入Server端本地网络
此时的VPN网络只包含OpenVPN Server和各个OpenVPN Clients。要实现我们的目标,首先要将Server端(slk-home-gate)的本地网络(home-work网络)包含进来:
push "route 10.10.10.0 255.255.255.0"
加入slk-away-gate的本地网络
接下来要将作为OpenVPN Client之一的slk-away-gate的本地网络(away-work网络)包含进VPN网络。
首先在/etc/openvpn目录下新建子目录ccd(代表client-config-dir):
# mkdir /etc/openvpn/ccd
在ccd目录下创建与每个OpenVPN Client相关的配置文件,文件以OpenVPN Client证书的Common Name命名,这个例子的文件名是slk-away-gate。文件内容:
iroute 10.20.10.0 255.255.255.0
然后编辑server.conf,添加:
client-config-dir ccd route 10.20.10.0 255.255.255.0
让OpenVPN Clients可以互访
虽然都在VPN网络里,但缺省模式下,OpenVPN Clients只能与OpenVPN Server通信,彼此不能通信。要允许这个功能,需要配置:
client-to-client
让别的OpenVPN Clients可以与away-work网络互访
虽然之前已经将away-work网络加入到VPN网络里,但只能与OpenVPN Server端机器互访,因为其他OpenVPN Clients的路由表不知道如何到达away-work网络。为此增加一条路由:
push "route 10.20.10.0 255.255.255.0"
降低OpenVPN进程权限
这是一个安全方面的考虑,在OpenVPN进程启动完成后,将进程权限由超级用户降为普通用户权限:
user nobody group nobody
至此,就是实现我们目标的最基本配置。
OpenVPN Client配置
OpenVPN Clients的配置都是类似的,这里以slk-away-gate为例。
获得密钥
从PKI获得CA证书、自己的证书和私钥,并放到相应位置:
- ca.crt → /etc/openvpn/certs/
- slk-away-gate.crt → /etc/openvpn/certs/
- slk-away-gate.key → /etc/openvpn/keys/
复制配置文件
同样先复制一份OpenVPN提供的Client配置样例,再做修改:
# cd /etc/openvpn/ # cp /usr/doc/openvpn-2.2.2/sample-config-files/client.conf .
接下来编辑client.conf进行设置。
设置密钥
首先设置各个密钥信息:
ca certs/ca.crt cert certs/slk-away-gate.crt key keys/slk-away-gate.key
设置OpenVPN Server的地址
指定OpenVPN Server的IP地址和端口:
remote 172.16.0.10 1194
降低OpenVPN进程权限
在OpenVPN进程启动完成后,将进程权限由超级用户降为普通用户权限:
user nobody group nobody
配置完毕。
启动OpenVPN
首先启动OpenVPN Server,在slk-home-gate执行:
# cd /etc/openvpn/ # openvpn server.conf
然后启动OpenVPN Clients,与OpenVPN Server连接:
# cd /etc/openvpn/ # openvpn client.conf
配置无误的话,VPN网络就搭建起来了。可以先关闭iptables防火墙,进行各种测试,看是否与预期一致。
iptables防火墙设置
测试通过后,iptables防火墙还得恢复。slk-home-gate和slk-away-gate之前运行的都是网关模板的脚本,详情可参见iptables脚本。
接下来就看,在引入OpenVPN后,脚本需要做那些调整。
首先,OpenVPN Server缺省监听在1194的UDP端口,所以,Server端需要打开该端口:
# 3.4.2 Allow OpenVPN (only for server). # $IPTABLES -A INPUT -i $WAN_IFACE -p udp --dport 1194 -m state \ --state NEW -j ACCEPT
相应的,OpenVPN Client要能连接Server的1194端口:
# 3.5.10 Allow OpenVPN(only for client). # $IPTABLES -A OUTPUT -o $WAN_IFACE -d $VPN_SERVER_IP -p udp --dport 1194 \ -m state --state NEW -j ACCEPT
OpenVPN启动后,会建立新的网络接口,如tun0(routed模式),相当于在原有网络基础上,又多了一个子网。自然的,需要针对新接口制定一些新规则。
增加新接口的配置信息:
# 1.6 VPN configuration. # VPN_IP="10.10.40.1" VPN_IFACE="tun+" VPN_BROADCAST="10.10.40.255" VPN_SERVER_IP="172.16.0.10"
增加内核模块的装载:
$MODPROBE tun
在Input链,允许在VPN接口接受ping请求:
$IPTABLES -A INPUT -i $VPN_IFACE -p icmp --icmp-type echo-request -j ACCEPT
在Forward链,允许内网与VPN网互访,这也是我们搭建VPN的目的。当然,也可制定更细粒度的规则:
# 3.6.5 LAN --> VPN rules. # # 3.6.5.1 Allow full access. # $IPTABLES -A FORWARD -i $LAN_IFACE -o $VPN_IFACE -m state \ --state NEW -j ACCEPT # # 3.6.6 LAN <-- VPN rules. # # 3.6.6.1 Allow full access. # $IPTABLES -A FORWARD -i $VPN_IFACE -o $LAN_IFACE -m state \ --state NEW -j ACCEPT
在iptables脚本提供了一份融合了上述配置的OpenVPN网关模板,可点击其中的脚本类型进行下载。