膜法家

如何在 Ubuntu 16.04 上用 StrongSwan 搭建 IKEv2 VPN 服务器

rASP
Aug 17, 2017
阅读本文需要 22 分钟

本文翻译自 How to Set Up an IKEv2 VPN Server with StrongSwan on Ubuntu 16.04


导入

VPN(Virtual Private Network,虚拟专用网络)可以帮助你在一个不安全的网络环境(比如机场、咖啡厅里的开放式无线网络)中使用加密的网络隧道来安全地访问互联网。

IKEv2(Internet Key Exchange v2)是一个允许服务器和客户端用IPSec隧道直接连接的协议。在 IKEv2 VPN 实施中,使用 IPSec 来加密网络流量。IKEv2 被许多新平台原生支持(如 OS X 10.11+, iOS 9.1+, and Windows 10)。

在这篇教程中,你将在一台装有 Ubuntu 16.04 的服务器上使用 StrongSwan 来搭建 IKEv2 VPN 服务器。


先决条件

为了完成这篇教程,你需要:


Step 1 - 安装 StrongSwan

首先,我们将安装 StrongSwan,这是一个开源的 IPSec 守护进程,我们将用它来配置我们的 VPN 服务器。我们也会安装 StrongSwan EAP 插件,它将提供相对于证书认证的密码认证功能。在这之后,我们会创建一些防火墙规则。

执行下面的命令来安装我们所需的组件:

sudo apt-get install strongswan strongswan-plugin-eap-mschapv2 moreutils iptables-persistent

注意:当安装 iptables-persistent 时,安装器将会询问是否保存现有的 IPv4 和 IPv6 规则。为保持已有的规则不变,我们都选择是。

现在,所有的东西都已经安装完成,让我们开始创建证书吧。


Step 2 - 建立证书认证

一个 IKEv2 服务器需要一个证书来向客户端证明自己的身份。为了帮助我们创建所需要的证书,StrongSwan 附带了一个用于生成证书颁发机构和服务器证书的小组件。

首先,让我们建立一个目录来储存我们所需要的东西:

mkdir vpn-certs
cd vpn-certs

现在,我们有了一个可以储存任何东西的目录啦!让我们开始生成我们的 root 密钥吧!我们将用一个将是一个4096位的 RSA 密钥来给我们的根证书颁发机构签名,所以我们一定要保证这个密钥的安全性!!

执行下面的命令来生成并保护密钥:

ipsec pki --gen --type rsa --size 4096 --outform pem > server-root-key.pem
chmod 600 server-root-key.pem

既然有了一个密钥,我们就可以继续来建立我们的根证书颁发机构并使用密钥来给根证书签名:

ipsec pki --self --ca --lifetime 3650 \
--in server-root-key.pem \
--type rsa --dn "C=US, O=VPN Server, CN=VPN Server Root CA" \
--outform pem > server-root-ca.pem

你可以更改 distinguished name 值,例如国家、组织、通称。这里的通称只是一个指示,所以你可以随便起一个名字。

之后,我们将根证书(server-root-ca.pem)复制到我们的客户端设备上,以便它们来验证服务器的真实性。

既然我们已经有了我们的根证书颁发机构,是时候开始创建一个 VPN 服务器使用的证书了。


Step 3 - 生成一个 VPN 服务器使用的证书

我们将为 VPN 服务器建立创建一个证书,它将允许客户端来验证服务器的真实性。

首先,用下面的命令来为服务器创建一个私钥:

ipsec pki --gen --type rsa --size 4096 --outform pem > vpn-server-key.pem

然后用 CA 密钥来创建并签署我们的 VPN 服务器证书。执行下面的命令,但是注意修改通称(Common Name,CN)和主题备用名称(Subject Alternative Name,SAN)域:

ipsec pki --pub --in vpn-server-key.pem \
--type rsa | ipsec pki --issue --lifetime 1825 \
--cacert server-root-ca.pem \
--cakey server-root-key.pem \
--dn "C=US, O=VPN Server, CN=server_name_or_ip" \
--san server_name_or_ip \
--flag serverAuth --flag ikeIntermediate \
--outform pem > vpn-server-cert.pem

将证书复制到一个 StrongSwan 可读的目录中:

sudo cp ./vpn-server-cert.pem /etc/ipsec.d/certs/vpn-server-cert.pem
sudo cp ./vpn-server-key.pem /etc/ipsec.d/private/vpn-server-key.pem

最后,修改这些密钥的读写权限来保证其安全:

sudo chown root /etc/ipsec.d/private/vpn-server-key.pem
sudo chgrp root /etc/ipsec.d/private/vpn-server-key.pem
sudo chmod 600 /etc/ipsec.d/private/vpn-server-key.pem

在这一步骤中,我们创建了一对用来保护客户端和服务器通讯的证书。我们也用了根密钥来签署这些证书,所以客户端可以用它来验证服务器的真实性。接下来我们将要开始配置软件。


Step 4 - 配置 StrongSwan

我们已经创建了所需的证书,是时候来配置 StrongSwan 啦!

StrongSwan 有一个默认配置文件,所以在我们进行修改前,最好先把它备份一下:

sudo cp /etc/ipsec.conf /etc/ipsec.conf.original

默认的配置文件长的不得了,为了避免我们在修改时出错,我们最好自己写一份。首先,清理我们原有的配置文件:

echo '' | sudo tee /etc/ipsec.conf

然后再你的文字编辑器中打开文件:

sudo nano /etc/ipsec.conf

首先,我们我们要 StrongSwan 记录后台情况并且允许复制连接。把以下几行添加至配置文件中:

/etc/ipsec.conf

config setup
  charondebug="ike 1, knl 1, cfg 0"
  uniqueids=no

然后我们将为我们的 VPN 设置一个控制块。我们也将告诉 StrongSwan 来创建一个 IKEv2 VPN 隧道并且在它启动时自动读取这些配置。在配置文件后加上以下代码:

/etc/ipsec.conf

/etc/ipsec.conf
conn ikev2-vpn
  auto=add
  compress=no
  type=tunnel
  keyexchange=ikev2
  fragmentation=yes
  forceencaps=yes

接下来我们将告诉 StrongSwan 我们将使用的加密算法。添加以下代码:

/etc/ipsec.conf

  ike=aes256-sha1-modp1024,3des-sha1-modp1024!
  esp=aes256-sha1,3des-sha1!

我们将配置对等体(dead-peer)检测来清理所有的“悬摆(dangling)”连接,以免客户端突然断线。添加以下代码:

/etc/ipsec.conf

  dpdaction=clear
  dpddelay=300s
  rekey=no

接着我们将配置服务器(left)侧的 IPSec 参数。添加以下代码:

/etc/ipsec.conf

  left=%any
  leftid=@server_name_or_ip
  leftcert=/etc/ipsec.d/certs/vpn-server-cert.pem
  leftsendcert=always
  leftsubnet=0.0.0.0/0

注意:当配置服务器 ID(leftid)时,只有 在你的 VPN 服务器需要使用域名解析时才添加@

leftid=@vpn.example.com

如果使用 IP 地址来访 问服务器,只需填入 IP 地址即可:

leftid=111.111.111.111

然后我们将配置客户端(right)侧的 IPSec 参数,比如私有 IP 地址、使用的 DNS 服务器:

/etc/ipsec.conf

  right=%any
  rightid=%any
  rightauth=eap-mschapv2
  rightsourceip=10.10.10.0/24
  rightdns=8.8.8.8,8.8.4.4
  rightsendcert=never

最后,我们要求 StrongSwan 在客户端发起连接请求时提供身份认证:

/etc/ipsec.conf

 eap_identity=%identity

最终版的配置文件应该像这样:

/etc/ipsec.conf

config setup
    charondebug="ike 1, knl 1, cfg 0"
    uniqueids=no

conn ikev2-vpn
    auto=add
    compress=no
    type=tunnel
    keyexchange=ikev2
    fragmentation=yes
    forceencaps=yes
    ike=aes256-sha1-modp1024,3des-sha1-modp1024!
    esp=aes256-sha1,3des-sha1!
    dpdaction=clear
    dpddelay=300s
    rekey=no
    left=%any
    leftid=@server_name_or_ip
    leftcert=/etc/ipsec.d/certs/vpn-server-cert.pem
    leftsendcert=always
    leftsubnet=0.0.0.0/0
    right=%any
    rightid=%any
    rightauth=eap-mschapv2
    rightdns=8.8.8.8,8.8.4.4
    rightsourceip=10.10.10.0/24
    rightsendcert=never
    eap_identity=%identity

确认无误后保存并关闭文件。

既然我们已经配置好了 VPN 参数,让我们着手建立我们的用户账户吧!


Step 5 - 配置 VPN 认证

我们的 VPN 服务器已经被配置成接受客户端连接了,但是我们还没有配置连接用的凭证,所以我们要在 ipsec.secrets 中配置这些东西:

  • 我们要告诉 StrongSwan 我们私钥储存的路径,以便服务器来加密、解密数据。
  • 我们需要建立一个可以连接服务器的用户白名单。

让我们打开并编辑这个文件:

sudo nano /etc/ipsec.secrets

首先,我们将告诉 StrongSwan 寻找密钥的路径:

/etc/ipsec.secrets

server_name_or_ip : RSA "/etc/ipsec.d/private/vpn-server-key.pem"

然后我们将创建用户凭证:

/etc/ipsec.secrets

your_username %any% : EAP "your_password"

保存并关闭文件。重新启动 VPN 服务以便应用我们的新配置:

sudo ipsec reload

既然我们的 VPN 服务器已经配置完成,是时候去设置我们的防火墙了。


Step 6 - 配置防火墙与内核 IP 转发

现在我们需要让防火墙允许 VPN 流量通过以及转发它们。我们将用 IPTables 来完成。

首先,如果你曾经设立过 UFW,请禁用它:

sudo ufw disable

然后移除所有 UFW 所建立的防火墙规则:

iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -F
iptables -Z

为了防止我们的 SSH 通道被关闭,我们允许所有以备允许的连接。为了以后的 SSH 连接,我们也将打开服务器的 22 端口。执行以下命令:

sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

我们也需要允许本地回路的连接:

sudo iptables -A INPUT -i lo -j ACCEPT

然后我们要告诉 IPTables 允许 IPSec 连接:

sudo iptables -A INPUT -p udp --dport  500 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 4500 -j ACCEPT

接着,我们要告诉 IPTables 去转发 ESP(Encapsulating Security Payload)流量,以便 VPN 客户端能连接服务器。ESP 能为 VPN 包在不安全的网络环境下提供多一层的安全:

sudo iptables -A FORWARD --match policy --pol ipsec --dir in  --proto esp -s 10.10.10.10/24 -j ACCEPT
sudo iptables -A FORWARD --match policy --pol ipsec --dir out --proto esp -d 10.10.10.10/24 -j ACCEPT

我们的服务器就像是我们的客户端与互联网中的一个网关。因为一个 VPN 服务器只有一个公网 IP 地址,我们需要伪造 IP 地址,以便以客户端的身份访问网络:

sudo iptables -t nat -A POSTROUTING -s 10.10.10.10/24 -o eth0 -m policy --pol ipsec --dir out -j ACCEPT
sudo iptables -t nat -A POSTROUTING -s 10.10.10.10/24 -o eth0 -j MASQUERADE

为了防止包缺失,我们将让 IPTables 减小包的大小:

sudo iptables -t mangle -A FORWARD --match policy --pol ipsec --dir in -s 10.10.10.10/24 -o eth0 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360

为了更好的安全性,我们将丢弃那些不符合我们配置的包:

sudo iptables -A INPUT -j DROP
sudo iptables -A FORWARD -j DROP

现在我们将永久保存这些规则,以免以后重新启动服务器导致配置丢失:

sudo netfilter-persistent save
sudo netfilter-persistent reload

最后,我们将启用服务器的包转发,编辑/etc/sysctl.conf

sudo nano /etc/sysctl.conf

我们将在这配置以下功能:

  • 启用 IPv4 包转发
  • 禁用 MTU
  • 禁用 ICMP 重定向

/etc/sysctl.conf

. . .

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

. . .

# Do not accept ICMP redirects (prevent MITM attacks)
net.ipv4.conf.all.accept_redirects = 0
# Do not send ICMP redirects (we are not a router)
net.ipv4.conf.all.send_redirects = 0

. . .

net.ipv4.ip_no_pmtu_disc = 1

修改文件并保存,重新启动服务器:

sudo reboot

服务器端的配置就到此为止了!


Step 7 - 测试 VPN 连接

现在,我们已经完成了服务器端的所有配置,来试试看能不能顺利连接吧!

首先,我们需要把根证书复制并安装到客户端设备上。最简单的办法就是登陆进你的服务器并执行以下命令:

cat ~/vpn-certs/server-root-ca.pem

你将看见类似的输出:

-----BEGIN CERTIFICATE-----
MIIFQjCCAyqgAwIBAgIIFkQGvkH4ej0wDQYJKoZIhvcNAQEMBQAwPzELMAkGA1UE

. . .

EwbVLOXcNduWK2TPbk/+82GRMtjftran6hKbpKGghBVDPVFGFT6Z0OfubpkQ9RsQ
BayqOb/Q
-----END CERTIFICATE-----

将这个输出复制到你的电脑上,包括 -----BEGIN CERTIFICATE----------END CERTIFICATE-----,保存成一个以.pem为后缀名的文件,例如:vpn_root_certificate.pem

另外,你也可以使用 SFTP 来传输这个证书。

一旦你将这个证书保存到电脑上,就可以建立与 VPN 服务器的连接了。鉴于已经有很多关于客户端的配置的教程,本文就不再赘述。


总结

在这篇教程里,你已经搭建了一个使用 IKEv2 协议的 VPN 服务器。无论你走到何处,你的通讯都是安全的了!

需要添加或者删除用户,只需要回到 Step 5 即可。每一行都代表一个用户,所以只要编辑以下文件就可以轻松的添加或删除用户啦!

你可能还会对EFF 保护线上安全的 12 个方法(En)感兴趣…