响水凹

欢迎来到 Guang-Wen Duan (Dennis Duan) 的个人 Wiki

用户工具

站点工具


computer:sec:openvpn

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还有很多功能,更多细节可参考官方的HowtoManual

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网关模板,可点击其中的脚本类型进行下载。

computer/sec/openvpn.txt · 最后更改: 2014/11/01 02:02 由 127.0.0.1