# OpenVPN (简体中文)

Related articles

- OpenVPN in Linux containers

This article or section is out of date.

Reason: 本文已与英文版本脱节 (Discuss in Talk:OpenVPN (简体中文)#)

本文中介绍了 OpenVPN 的基本的安装与配置过程，适用于个人使用与小型商业使用。要了解更多信息，请访问官方网站 HOWTO、OpenVPN 2.3 手册页 以及 Manual。

OpenVPN 是一个健壮的、高度灵活的 VPN 守护进程。它支持 SSL/TLS 安全、Ethernet bridging、经由代理的 TCP 或 UDP 隧道和 NAT。另外，它也支持动态 IP 地址以及 DHCP，可伸缩性足以支持数百或数千用户的使用场景，同时可移植至大多数主流操作系统平台上。

OpenVPN 与 OpenSSL 库紧密相关，并由此获得许多加密功能。

## 安装

安装位于官方软件源的 openvpn。

Note: 该软件包同时包含服务器和客户端软件，故你应该在所有需要创建 VPN 连接的机器上安装它。

## 内核配置

OpenVPN 需要 TUN/TAP 的支持，默认内核已经进行了正确的配置。

自定义的内核需要启用 `tun` 模块，详情参阅 Kernel modules

    Kernel config file

     Device Drivers
      --> Network device support
        [M] Universal TUN/TAP device driver support

## 准备证书和密钥数据

现在要创建所需的证书和密钥，可以在任何机器上完成，即使没有联网也可以进行。 设置证书和密钥生成脚本的默认值。编辑 `/etc/openvpn/easy-rsa/vars`，设置 KEY_COUNTRY, KEY_PROVINCE, KEY_CITY, KEY_ORG 和 KEY_EMAIL 参数(不要留空任何参数)，然后导出环境变量。

    # source ./vars

清理之前的密钥：

    # ./clean-all

build-ca 脚本创建了 certificate authority (CA) ca.key，密钥认证机器需要这个密钥。服务器和客户端需要 ca.crt 证书。

    # ./build-ca

`build-key-server` 为服务器创建一个证书和密钥对。使用中不要输入简单的密码或公司名。

    # ./build-key-server <server-name>

`build-dh` 脚本创建服务器需要的 Diffie-Hellman pem 文件。

    # ./build-dh

`build-key` 脚本创建客户端证书和密钥对。可以生成任意多个以给不同的客户端使用。只要保证客户端名 <client> 是唯一的。如果要用密码认证客户端，请使用 `build-key-pass` 脚本。

    # ./build-key <client1>
    # ./build-key <client2>

生成的文件都保存在 `/etc/openvpn/easy-rsa/keys`。如果有错误，可以通过运行 `clean-all` 脚本，然后从头开始。注意这将删除之前生成的证书和密钥。

    # ./clean-all

最后一步是将所有需要的文件通过安全通道放到正确的机器上。`ca.crt` 需要放到所有服务器和客户端。`server.crt`, `server.key` 和 `dh{n}.pem` 文件放到服务器， `client.crt` 和 `client.key` 文件放到客户端。

## 配置服务器

### 复制默认服务器配置文件

    # cp /usr/share/openvpn/examples/server.conf /etc/openvpn/openvpn.conf

### 使用 PAM 和密码认证

    port 1194
    proto udp
    dev tap
    ca /etc/openvpn/easy-rsa/keys/ca.crt
    cert /etc/openvpn/easy-rsa/keys/<MYSERVER>.crt
    key /etc/openvpn/easy-rsa/keys/<MYSERVER>.key
    dh /etc/openvpn/easy-rsa/keys/dh1024.pem
    server 192.168.56.0 255.255.255.0
    ifconfig-pool-persist ipp.txt
    ;learn-address ./script
    client-to-client
    ;duplicate-cn
    keepalive 10 120
    ;tls-auth ta.key 0
    comp-lzo
    ;max-clients 100
    ;user nobody
    ;group nobody
    persist-key
    persist-tun
    status /var/log/openvpn-status.log
    verb 3
    client-cert-not-required
    username-as-common-name
    plugin /usr/lib/openvpn/openvpn-auth-pam.so login

### 使用证书认证

    port 1194
    proto tcp
    dev tun0

    ca /etc/openvpn/easy-rsa/keys/ca.crt
    cert /etc/openvpn/easy-rsa/keys/<MYSERVER>.crt
    key /etc/openvpn/easy-rsa/keys/<MYSERVER>.key
    dh /etc/openvpn/easy-rsa/keys/dh1024.pem

    server 10.8.0.0 255.255.255.0
    ifconfig-pool-persist ipp.txt
    keepalive 10 120
    comp-lzo
    user nobody
    group nobody
    persist-key
    persist-tun
    status /var/log/openvpn-status.log
    verb 3

    log-append /var/log/openvpn
    status /tmp/vpn.status 10

### 通过服务器路由

将下面内容写入服务器的 `openvpn.conf` 配置文件，"192.168.1.1" 修改为外部 DNS IP 地址。

    push "dhcp-option DNS 192.168.1.1"
    push "redirect-gateway def1"

使用 iptable 进行 NAT 转发：

    echo 1 > /proc/sys/net/ipv4/ip_forward
    iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

如果运行在 OpenVZ VPS 环境，参见 [1]:

    iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o venet0 -j SNAT --to (venet0 ip)

如果一切正常，保存修改，编辑 `/etc/conf.d/iptables` 设置 IPTABLES_FORWARD=1

    /etc/rc.d/iptables save

## 客户端配置

配置客户端的 .conf 文件

### 使用密码认证

    client
    dev tap
    proto udp
    remote <address> 1194
    resolv-retry infinite
    nobind
    persist-tun
    comp-lzo
    verb 3
    auth-user-pass passwd
    ca ca.crt

被 `auth-user-pass` 引用的 `passwd` 文件必须包含如下两行:

- 第一行 - username
- 第二行 - password

### 证书验证

    client
    remote <MYSERVER> 1194
    dev tun0
    proto tcp
    resolv-retry infinite
    nobind
    persist-key
    persist-tun
    verb 2
    ca ca.crt
    cert client1.crt
    key client1.key
    comp-lzo

将`ca.crt`, `client1.crt` 和 `client1.key`复制到远程计算机：

安装隧道模块:

     # sudo modprobe tun

要让 tun 模块自动启动，请将其加入 `/etc/rc.conf` 的 Modules 行。

### DNS

系统使用的 DNS 服务器定义在`/etc/resolv.conf`。通常此文件由控制系统网络的模块(Wicd, NetworkManager 等)维护。然而，如果希望通过远程服务器解析地址，OpenVPN 需要修改这个文件。

安装 openresolv软件包，它可以实现多个程序互不影响的修改 `resolv.conf`。安装后通过重启网络连接，保证 resolv.conf 是由 "resolvconf" 创建而且 DNS 解析工作正常。openresolv 不需要配置，它会自动检测和使用网络系统。

然后将如下脚本保存到`/usr/share/openvpn/update-resolv-conf`:

    #!/bin/bash
    #
    # Parses DHCP options from openvpn to update resolv.conf
    # To use set as 'up' and 'down' script in your openvpn *.conf:
    # up /etc/openvpn/update-resolv-conf
    # down /etc/openvpn/update-resolv-conf
    #
    # Used snippets of resolvconf script by Thomas Hood <jdthood@yahoo.co.uk>
    # and Chris Hanson
    # Licensed under the GNU GPL.  See /usr/share/common-licenses/GPL.
    #
    # 05/2006 chlauber@bnc.ch
    #
    # Example envs set from openvpn:
    # foreign_option_1='dhcp-option DNS 193.43.27.132'
    # foreign_option_2='dhcp-option DNS 193.43.27.133'
    # foreign_option_3='dhcp-option DOMAIN be.bnc.ch'

    [ -x /usr/sbin/resolvconf ] || exit 0

    case $script_type in

    up)
       for optionname in ${!foreign_option_*} ; do
          option="${!optionname}"
          echo $option
          part1=$(echo "$option" | cut -d " " -f 1)
          if [ "$part1" == "dhcp-option" ] ; then
             part2=$(echo "$option" | cut -d " " -f 2)
             part3=$(echo "$option" | cut -d " " -f 3)
             if [ "$part2" == "DNS" ] ; then
                IF_DNS_NAMESERVERS="$IF_DNS_NAMESERVERS $part3"
             fi
             if [ "$part2" == "DOMAIN" ] ; then
                IF_DNS_SEARCH="$part3"
             fi
          fi
       done
       R=""
       if [ "$IF_DNS_SEARCH" ] ; then
               R="${R}search $IF_DNS_SEARCH
    "
       fi
       for NS in $IF_DNS_NAMESERVERS ; do
               R="${R}nameserver $NS
    "
       done
       echo -n "$R" | /usr/sbin/resolvconf -a "${dev}.inet"
       ;;
    down)
       /usr/sbin/resolvconf -d "${dev}.inet"
       ;;
    esac

设置脚本可执行属性：

    $ chmod +x /usr/share/openvpn/update-resolv-conf

然后将下面内容加入 OpenVPN 客户端的配置文件：

    script-security 2
    up /usr/share/openvpn/update-resolv-conf
    down /usr/share/openvpn/update-resolv-conf

现在再启动 OpenVPN 连接，就能发现 `resolv.conf` 文件已经更新，关闭连接后恢复正常。

## 启动 OpenVPN

### 手动启动

如需对 VPN 连接进行调试，可以以 root 身份手动运行 `openvpn /etc/openvpn/client.conf` 以启动客户端守护程序。服务器端同样可以如此启动，只需替换为服务器端的配置文件（例，`openvpn /etc/openvpn/server.conf`）。

### systemd 服务配置

若需在系统启动时自动启动 OpenVPN，对服务器端与客户端，都可以采用在对应机器上 启用 `openvpn@<configuration>.service` 的方式配置。

例如，如果客户端配置文件是 `/etc/openvpn/client.conf`，则服务名称应为 `openvpn@client.service`。或者，如果服务器端配置文件是 `/etc/openvpn/server.conf`，则服务名称应为 `openvpn@server.service`。

### 让 NetworkManager 启动连接

在客户端，您可能并不需要一直运行 VPN 隧道，或者您仅仅想要为特定的 NetworkManager 连接建立隧道。要实现这一点，您可以向 `/etc/NetworkManager/dispatcher.d/` 添加脚本。在下列示例中，"Provider" 是 NetworkManager 连接的名称：

    /etc/NetworkManager/dispatcher.d/10-openvpn

    #!/bin/bash

    case "$2" in
      up)
        if [ "$CONNECTION_ID" == "Provider" ]; then
          systemctl start openvpn@client
        fi
      ;;
      down)
        systemctl stop openvpn@client
      ;;
    esac

请查看 NetworkManager#Network services with NetworkManager dispatcher 以了解详情。

### Gnome 配置

如果您想要经由 Gnome 内置的网络配置来连接到一个 OpenVPN 服务器，请按照如下步骤进行配置： 首先，安装 `networkmanager-openvpn`。 然后，go to the Settings menu and choose Network. Click the plus sign to add a new connection and choose VPN. From there you can choose OpenVPN and manually enter the settings, or you can choose to import #The client configuration file[broken link: invalid section] if you have already created one. If you followed the instructions in this article then it will be located at `/etc/openvpn/client.conf`. To connect to the VPN simply turn the connection on.

## 参见

- OpenVPN 官方站点
- Airvpn

Categories:

- 简体中文
- Virtual Private Network (简体中文)

Hidden categories:

- Pages or sections flagged with Template:Out of date
- Pages with broken section links