使用 Strongswan 架设 Ipsec VPN

跳转至: 导航, 搜索

本教学介绍了如何使用 Strongswan 5.0.x 在 openSUSE 12.3+ 服务器上架设支持 ikev1/ikev2 的 Ipsec VPN。适用于 openSUSE、iOS、Android、Windows 和其它 Linux。
注意: Strongswan 5 即现在的主力支持版本和 Strongswan 4 的 ipsec.conf 有很大的不同(作废了很多选项),请保证您的版本为 5.0.4+ 本教学才有参考价值。因此请不要往 Debian 这些软件包版本旧的系统上套,同样 openSUSE 用户也不要拿 Debian 的来套。
注意: 本文的例子仅以最常见的 VPS/客户机模式为例,假设客户机使用图形客户端,因此并不涉及客户端文本配置的内容。其中的原理和服务器端配置可用于其它用途比如服务器到服务器(Site to Site)的连接,但这种连接的客户端文本配置部分需要领会原理自己写。
注意: 本文只适用于有 VPS 的爱好者使用,并不提供已建立好的 demo 供测试,但保证文中出现的配置如无意外如上游改选项,实际中都是能够使用的。因此并不可用于「免费 VPN」这样的话题,如何优惠购买 VPS 请到我们的论坛 forum.suse.org.cn。本文也不讨论如何进行后台计费,但提供了计费软件的名称供 VPN 服务商参考,因此只适用于小团体的共用。如果小群体产生流量纠纷而需区分账户,那解散才是治本的方法,其它都只能治标。

什么是 IPsec?

IPsec 是 虚拟私密网络(VPN) 的一种,用于在服务器和客户端之间建立加密隧道并传输敏感数据之用。它由两个阶段组成,第一阶段(Phrase 1, ph1),交换金钥建立连接,使用互联网金钥交换(ike)协议; 第二阶段(Phrase 2, ph2),连接建立后对数据进行加密传输,使用封装安全载荷(esp)协议。参考:维基百科 IPsec 词条

其中,第一阶段和第二阶段可以使用不同的加密方法(cipher suites)。甚至,第一阶段 ike 协议的第一版(ikev1)有两种模式,主力模式(main mode)和积极模式(aggressive mode),主力模式进行六次加密握手,而积极模式并不加密,以实现快速建立连接的目的。

第一阶段的 ike 协议有两个版本(ikev1/ikev2),不同的开源/闭源软件实现的版本均不同,不同的设备实现的版本也不同。再联系到第一阶段/第二阶段使用的各种不同加密方法,使得 IPsec 的配置有点黑魔法的性质,要么完全懂,通吃; 要么完全不懂,照抄。

设备/操作系统规格

这里主要介绍了设备/操作系统使用的 ike 版本及其特殊要求。

Linux

命令行客户端就是 strongswan 本身,因此完美兼容,支持 ikev1/ikev2 和所有加密方法的连接。因此如果用户只使用 Linux 命令行客户端,不使用各种移动设备也不使用 Windows,那么完全没有那么多事。

但 Linux 的图形界面客户端 NetworkManager-strongswan 目前只支持 ikev2 连接,必须使用证书或 EAP (各种加密方法都支持,包括微软的 MSCHAPv2)进行认证,不支持纯密码(PSK)认证。这并不是 strongswan 的错误,或者技术不行(开源总是走在技术最前沿的,毕竟命令行是支持的),而仅仅是体现一种选择:ikev1 被 strongswan 项目认为是该淘汰的协议,而 PSK 加密被认为是非常不安全的。参考 strongswan 维基 NetworkManager 词条

Android

Android 和 Linux 不一样,只支持 ikev1。其它方面和 Linux 一样,甚至有好多种 IPsec VPN 配置模式可供选择。

iOS/Mac OS X

它们声明使用的 IPsec 客户端为 Cisco,实际为自己修改的 racoon。它只支持 ike 协议的第一版即 ikev1,可以使用证书或纯密码(PSK)认证,但必须辅之 xauth 用户名/密码认证。

该修改版的 racoon 会优先使用不加密的积极模式,而积极模式是 strongSwan 所不支持的。所以要使用主力模式。

iOS 6 还有一个「衔尾」故障:它在第一阶段握手时会把数据包拆分成小块(fragmentation),然后「加密」发送。然而这种加密仅仅是声明的,其实并未加密,这就导致 strongSwan 及其它标准服务器端/Cisco 设备无法解密。另外 ikev1 的 fragmentation 插件是闭源的。开源服务器端无法对这些小块进行重组。参考:Cisco VPN stop working after upgrading to IOS 6

所以产生了一种权宜之计,就是使用小证书(小于 1024,默认一般为 2048),来达到不拆包的目的。但是 Mac OS X 10.7 的更新却对这种方式进行了封杀,学习微软加入了证书验证,小证书直接拒绝。

所幸 strongswan 5.0.2 已经完成了 fragmentation 的开源实现和对 iOS 那个声明加密其实未加密故障的处理:IKE message fragmentation (cisco) + IOS 6.0 Hack for encrypted flaged ike fragmentation packets,该链接中也能找到 strongswan 4 的补丁。

Windows

微软的差劲只比 iOS 好一点。好处在于它支持了 ikev2,但是只在 Windows 7 以后支持,Vista 之前依然使用 ikev1。

坏处在于它的 ikev2 支持非常诡异,指定了 Diffie Hellman group(DH,迪菲-赫尔曼密钥交换组)必须是 modp1024。这是非常少见理论上不应该由系统管理员操心的加密选项:

在 strongswan 中,定义第一阶段(ike)和第二阶段(esp)加密方法的语法是:

 ike/esp=encryption-integrity[-dhgroup][-esnmode]
 第一阶段/第二阶段=加密方法-健壮性认证方法 (后面两项可选)[-DH 组] [-扩展序列号支持模式(RFC4304)]

参考:IKEv2CipherSuites

Windows 定义了一个可选的选项,导致了我们必须去定义整个第一阶段的加密方法。这样被破解的可能性就提高了。

其次在于它的 rekey(重连)。IPsec 的认证是有时效的,超过时间会重新认证。这种 CHILD_SA 认证可由服务器发出,也可由客户端发出,一般是由服务器发出。但是 Windows 7 的 ikev2 的表现是,如果你在路由器(NAT)后,收到这种请求会把微软内部的通知代码发出去,代码为 12345, 经过 strongswan 项目侦错后发现这个代码的意思是 ERROR_IPSEC_IKE_INVALID_SITUATION。但是处理不了,它不是 IPsec 标准协议定义过的错误。

于是有两种权宜之计:

一种是让 Windows 7 来主动 rekey。Windows 7 rekey 的时间大约是 58 分 46 秒,所以要配置服务器 rekey 时间比它长。但是效果非常不好。因为 rekey 是由三个变量控制的,key 的生命周期,key 的边际时间(生命周期前多久进行 rekey),和边际时间误差(rekeyfuzz),误差是不可控的。参考:ExpiryRekey

即使能控制 strongswan 这边,Windows 依然是「大约」; 即使两边都能控制,假设服务器延后一秒 rekey,理论上如果连接持续时间足够长,依然能够撞车:58x60+46 次 rekey 后即 146 天后撞车,连一年都没有,在 Linux 服务器对 Windows 服务器这种使用实例中就明显不符合要求。

所以目前只能使用后一种方法即完全禁用服务器端 rekey。

最后,它的 EAP 认证也非常糟糕。MSCHAPv2 的 eap 身份不是 ikev2 身份(ikev2 身份一般是 EAP 用户名),所以必须在服务器端显式定义 eap_identity 来使用 Windows 7 的 eap 身份。

安装 Srongswan

sudo zypper ar -f http://download.opensuse.org/repositories/network:/vpn/openSUSE_12.3/ network:vpn
sudo zypper ref
sudo zypper in --no-recommends strongswan-ipsec

这里 --no-recommends 是不带推荐软件包,因为推荐的软件包都是针对桌面环境的,服务器用不到。

如果你的版本是 openSUSE 12.1/12.2,请相应替换源地址。

生成证书(可选)

注意: 如果不生成证书,后面配置部分的配置中用 pubkey 认证的 conn 都不能用,甚至不能保留在配置中。

每一个完整的 ssl 证书都有一个公钥和一个私钥,它们可以在一起也可以分开放(当然如果你要在网络上传输,肯定只能用公钥)。公钥是在网络上传输的,而私钥是藏好用来和接收到的公钥配对的(因此私钥里也有整个公钥,用来配对)。

生成 CA 证书

生成一个私钥:

ipsec pki --gen --outform pem > ca.pem

没什么好解释的,--outform 一共有三个格式可选,但是另外两个是 der 和 pgp...

基于这个私钥自己签一个 CA 证书:

ipsec pki --self --in ca.pem --dn "C=CN, O=strongSwan, CN=strongSwan CA" --ca --outform pem > ca.cert.pem

这里 --self 表示自签证书,--in 是输入的私钥,--dn 是判别名,--ca 表示生成 CA,其它同上。这里需要解释下判别名:

  • C 表示国家名,同样还有 ST 州/省名,L 地区名,STREET(全大写) 街道名。
  • O 表示组织名。
  • CN 为通用名。

具体见微软的文档:Distinguished Names

生成服务器证书

同样生成私钥:

ipsec pki --gen --outform pem > server.pem

用我们刚才自签的 CA 证书给自己发一个服务器证书:

 ipsec pki --pub --in server.pem | ipsec pki --issue --cacert ca.cert.pem \
--cakey ca.pem --dn "C=CN, O=strongSwan, CN=forum.suse.org.cn" \
--san="forum.suse.org.cn" --flag serverAuth --flag ikeIntermediate \
--outform pem > server.cert.pem

这条命令的意思解释下:

ipsec pki --pub --in server.pem 

是从我们刚生成的私钥里把公钥提取出来,然后用公钥去参与后面的服务器证书签发(这个是 VPN 连接时候要用的,你不想把私钥也给它吧?那样跟没签证书一样...)。

--issue, --cacert 和 --cakey 就是表明要用刚才自签的 CA 证书来签这个服务器证书。

--dn, --san,--flag 是一些客户端方面的特殊要求:

  • iOS 客户端要求 CN 也就是通用名必须是你的服务器的 URL 或 IP 地址;
  • Windows 7 不但要求了上面,还要求必须显式说明这个服务器证书的用途(用于与服务器进行认证),--flag serverAuth;
  • 非 iOS 的 Mac OS X 要求了「IP 安全网络密钥互换居间(IP Security IKE Intermediate)」这种增强型密钥用法(EKU),--flag ikdeIntermediate;
  • Android 和 iOS 都要求服务器别名(serverAltName)就是服务器的 URL 或 IP 地址,--san。

生成客户端证书

依然是生成私钥:

ipsec pki --gen --outform pem > client.pem

然后用刚才自签的 CA 证书来签客户端证书:

 ipsec pki --pub --in client.pem | ipsec pki --issue --cacert caCert.pem \
--cakey caKey.pem --dn "C=CN, O=strongSwan, CN=client" \
--outform pem > client.cert.pem

这时命令行会提示你输入两遍密码,这个就是你的客户端证书密码

看懂了服务器的,客户端的也就不难理解了。除了没有那一堆特殊要求别的都一样。

客户端证书可以每个客户端签一个,也可以让它们公用一个。是否多签看用途,一般用于区分设备(计费是不用这样的,是用账户来区分的)。

生成 pkcs12 证书(可选)

你可能还想生成一个可以直接导入的 pkcs12 证书(用于手机,诺基亚没这东西还不行):

 openssl pkcs12 -export -inkey client.pem -in client.cert.pem -name "client" \
-certfile ca.cert.pem -caname "strongSwan CA" -out client.cert.p12

安装证书

cp -r ca.cert.pem /etc/ipsec.d/cacerts/
cp -r server.cert.pem /etc/ipsec.d/certs/
cp -r server.pem /etc/ipsec.d/private/
cp -r client.cert.pem /etc/ipsec.d/certs/
cp -r client.pem /etc/ipsec.d/private/

CA 证书、客户证书(两个)和 .p12 证书用 FTP 复制出来给客户端用。有几种 Android 配置还需要服务器证书(server.cert.pem)。

配置 Strongswan

ipsec.conf

config setup
    uniqueids=never 

conn iOS_cert
    keyexchange=ikev1
    # strongswan version >= 5.0.2, compatible with iOS 6.0,6.0.1
    fragmentation=yes
    left=%defaultroute
    leftauth=pubkey
    leftsubnet=0.0.0.0/0
    leftcert=server.cert.pem
    right=%any
    rightauth=pubkey
    rightauth2=xauth
    rightsourceip=10.0.0.0/24
    rightcert=client.cert.pem
    auto=add

# also supports iOS PSK and Shrew on Windows
conn android_xauth_psk
    keyexchange=ikev1
    left=%defaultroute
    leftauth=psk
    leftsubnet=0.0.0.0/0
    right=%any
    rightauth=psk
    rightauth2=xauth
    rightsourceip=10.0.0.0/24
    auto=add

# compatible with "strongSwan VPN Client" for Android 4.0+
# and Windows 7 cert mode.
conn networkmanager-strongswan
    keyexchange=ikev2
    left=%defaultroute
    leftauth=pubkey
    leftsubnet=0.0.0.0/0
    leftcert=server.cert.pem
    right=%any
    rightauth=pubkey
    rightsourceip=10.0.0.0/24
    rightcert=client.cert.pem
    auto=add

conn windows7
    keyexchange=ikev2
    ike=aes256-sha1-modp1024! 
    rekey=no
    left=%defaultroute
    leftauth=pubkey
    leftsubnet=0.0.0.0/0
    leftcert=server.cert.pem
    right=%any
    rightauth=eap-mschapv2
    rightsourceip=10.0.0.0/24
    rightsendcert=never
    eap_identity=%any
    auto=add

其中 config setup 只能出现一次,而 conn <连接名称> 可以有很多个。这里的名称不是预定义的,可以随意写,只要你能识别就行,主要用来定义一种连接,就是为了让你在日志里好找。

新版 strongswan 里 config setup 的内容不如旧版的多,许多旧版必须有的选项都被作废了。比如:

  • plutostart 新版所有的 ike 协议都由原来 ikev2 的 daemon:charon 接管。根本就没有 pluto 了。
  • nat_traversal 新版所有的 ike 协议都是可以穿越路由器(NAT)的。
  • virtual_private 定义服务器的局域网 IP 地址。现在被魔术字 0.0.0.0/0 取代了。
  • pfs 完美向前保密,用于 rekey 时。意思是你现在的金钥互换过程如果被攻破了,会不会对已经互换过的金钥产生影响。以前一般设置成 no 来适用于 iOS 这种客户端会以积极模式发出非加密的 rekey 请求的情况。现在这个选项完全没作用了。第一阶段永远是完美向前保密的,第二阶段(esp)如果指定了 DH 组那么也是完美向前保密的,但是默认加密方法就已经指定了 DH 组。所以该选项永远为 yes。

而另外旧版和新版都有的选项也都定义了默认值,比如:

  • strictpolicy 是否一定需要证书吊销列表(CRL)的 URL。默认就是 no。
  • charonstart 是否启动 ikev2 的 daemon。这是旧版加入的,因为那个时候的主力是 pluto。现在默认就是 yes,你改成 no 那你连原先 pluto 的连接都无法连接,因为 ike 协议的实现全被 charon 接管了。

所以 config setup 基本上占位就行了。这里我们修改了 uniqueids 的值来实现多设备同时在线。

而 conn 最主要要理解左右的概念。其实左右是可以不分的,它们只是用来表示一个连接的两端。只是在如果你定义的不够全面时,左侧会默认被认为是本机(你的 VPS),右侧默认为他机(你的笔记本),即以左为尊。

  • left/right 是左右 id。它们用来识别服务器/客户端,可以是证书的判别名(DN),比如 "C=CN, O=strongSwan, CN=strongSwan CA",也可以是 IP 地址,也可以是 EAP 的用户名,还可以是魔术字 %any,表示什么都行。只是在 5.0.0 之前,为本机这边定义 %any 的话,ikev1 连接即 keyexchange=ikev1 的连接是识别不了,所以要改成 %defaultroute 表示自己从 ifconfig 里取 IP。为了和 right 的 %any 区分开,我们使用这种方法。所以说到最后这两个选项似乎没有什么用。但它们是必须的。
  • leftauth/rightauth 这是最重要的改动。新版主要是作废了之前的 authby 和 xauth=server/client 选项而都改用这种方法。因此使得 ikev1 也能够出现混血认证(左右两边认证的方法不同)了。参数主要有 pubkey 表示用证书,psk 表示用密码,eap 表示用扩展验证协议。
  • leftauth2/rightauth2 是为了应对旧版很常见的 authby=xauthpsk/xauthrsasig 的。现在 xauth 只能写在这里。而 psk 对应 leftauth/rightauth 里的 PSK 方法,rsasig 则对应 pubkey 方法。
  • leftsubnet 最重要的,引入了魔术字 0.0.0.0/0。如果你在右侧为客户端分配虚拟 IP 地址的话,那表示你之后要做 iptables 转发,那么左边就必须是用魔术字。
  • leftcert/rightcert 就是指定证书名字。
  • rightsourceip 为客户端分配的虚拟 IP 段。
  • auto 定义 strongswan 启动时该连接的行为。start 是启动; route 是添加路由表,有数据通过就启动; add 是添加连接类型但不启动; ignore 是当它不存在。默认是 ignore。看起来似乎是 route 比较好,但问题是我们服务器端不能预分配虚拟 IP,所以服务器端一般用的都是 add。而客户端文本配置可以选择 start。

另外说下旧版的 xauth=server/client 的问题。它表示在服务器端还是在客户端执行 xauth 认证。而在新版中主要通过左右方向来体现。比如你在服务器端执行认证,那认证请求是由客户端发出的,所以要写 rightauth2=xauth。如果在客户端执行认证,那认证请求是服务器发出的,所以要写 leftauth2=xauth。

另外网上很常见的一个配置选项是 leftfirewall=yes。这是完全错误的。看上去它的唯一作用是定义你的服务器是不是在防火墙后面,但实际上它是作为 ipsec_updown 脚本的参数被开发出来,是表明你的本机 subnet 是不是用 iptables 转发/伪装出来的。如果是的话,就调用 left/rightupdown 定义的路径下的脚本,脚本的作用是对通过 ipsec 连接的数据包进行 iptables 豁免。

之所以说它是错到离谱的(虽然没有产生影响),因为这些人完全就不懂,有公网 IP 的服务器的 subnet 很少是伪装的。另外必须写了脚本该选项才有意义,没看过一个定义了这个选项的人写过脚本。还有,leftsubnet=0.0.0.0/0 通过魔术字把 subnet 定义为了 any,你根本没法写脚本啊。所以我们这里完全就不用。

至于某类型连接,主要是根据设备规格定义的,一些特殊选项的解释如下:

  • fragmentation=yes 开启对 iOS 拆包的重组支持。
  • ike=aes256-sha1-modp1024! Windows 指定的第一阶段加密方法。
  • rekey=no 服务器对 Windows 发出 rekey 请求会断开连接。
  • rightsendcert=never 因为这是一个混血连接。服务器对自己的身份进行认证时使用的是证书,而服务器对客户端的认证使用的只是 eap-mschapv2。如果不设置的话默认是 ifasked,意思是如果服务器向客户端请求证书,客户端就会给它,但客户端给不出,连接就会断。这里设置为客户端永远不给,实际上的意思其实是服务器不要向客户端请求证书。
  • eap_identity=%any 使用 Windows 的 eap 身份。不然会出现”no eap key found for host <rightid>“错误。

ipsec.secrets

#
# ipsec.secrets
#
# This file holds the RSA private keys or the PSK preshared secrets for
# the IKE/IPsec authentication. See the ipsec.secrets(5) manual page.
#
: RSA server.pem
: PSK "PSK password"
marguerite : XAUTH "user password"
marguerite : EAP "user password"

看上去比较好理解,实际不是。

有些人可能会误以为:

: PSK "PSK password"
marguerite : XAUTH "user password"

是成对的,用于比如 android-xauth-psk 这样的连接,于是到了 iOS 的时候又写了一对:

: RSA server.pem
marguerite : XAUTH "user password"

来支持 iOS 的 RSA + XAUTH 认证。

这样做是没有必要的,上面定义的是种认证方法。它们之间是遵循「各找各妈」的原则的,可以任意混搭。即你写了一个 XAUTH 即可支持所有完全使用或部分使用 XAUTH 方法的连接。

实际上:

: PSK "PSK password" 

相当于:

%any %any : PSK "PSK password"

遵循:

主机 对等点 : 方法 <本机证书/协议密码> <本机证书密码>

的格式。以 :为分界,分别从左到右填充,除了各类密码缺失以 null 补位,其它都用 %any 补位(密码怎么可能是 %any)。

于是

marguerite : EAP "user password"

相当于

marguerite %any : EAP "user password" // EAP 方法没有证书,也就没有证书密码

这里有些人可能迷惑了,前面不是说过以左为尊、本机(这里是 VPS)默认在左边吗,你刚才定义 eap-mschapv2 的时候可是定义给的 rightauth,这次怎么把 EAP 的用户名写在左边了?

请注意,ipsec.conf 使用的是本机/他机的逻辑,本机默认在左; 而 ipsec.secrets 使用的是主机/对等点的逻辑,主机永远在左。

ipsec.conf 里面定义的是连接,左侧的本机(对你来说,本机是你的笔记本,而对服务器来说,本机是它自己,你才是它的「他机」,这个配置是在服务器上的,不要混淆)用证书认证,右侧是你的 win7 用 mschapv2 认证; 而 ipsec.secrets 里定义的是认证,认证过程是你的 win7 用这个用户名和后面定义的密码去连接主机,认证是主机上发生的,所以要写在左边。

另外一部分人可能会混淆主机/对等点的含义,认为他们和 BT 是一样的,你开启了一个 strongswan 连接,于是你是主机,而其它人都是对等点,于是他们统一了本机/他机和主机/对等点这两种截然不同的逻辑。前面已经说了我们的例子是以 VPS/客户机这种典型案例为主,而你的客户机是图形界面自适配的,你没有改过客户机的配置文件(所以官方维基上提供的例子你要看的是 moon 的配置),这种尴尬的统一的影响几乎没有。

而这种案例下,你不能理解主机/对等点的含义的后果是致命的:

你有一台国外 VPS,一台国内 VPS,想让国内 VPS 也能科学上网。那你在国内 VPS 上就可能产生这样的配置:

<国外 VPS 的 IP> <国内 VPS 的 IP> : RSA <国内 VPS 的私人证书名称> <私人证书密码>

国外 VPS:

<国外 VPS 的 IP> <国内 VPS 的 IP> : RSA <国外 VPS 的服务器证书名称> // 服务器证书一般没有密码

这里国外服务器是主机,国内服务器是对等点。主机永远只有一台,而且是在一开始便确定并固定不变的。如果你把国内 VPS 配置成:

<国内 VPS 的 IP> <国外 VPS 的 IP> : RSA <国内 VPS 的私人证书名称> <私人证书密码>

是无法连接的。因为主机始终是国外的 VPS。你可以想象为 BT 中心种子服务器和你的计算机的关系。中心种子服务器是固定不变的。

另外也间接证明了 ipsec 连接的代理是单向的,只能是主机为对等点做代理。就是说即使两台都是服务器,它们的 ipsec 连接也不是双向的,比如你国内服务器可以科学上网,而国外服务器可以看优酷,这是不可能在一个连接里发生的。

strongswan.conf

# strongswan.conf - strongSwan configuration file
charon {
       duplicheck.enable = no

       dns1 = 208.67.222.222
       dns2 = 208.67.220.220

       # for Windows only
       nbns1 = 208.67.222.222
       nbns2 = 208.67.220.220

       filelog {
               /var/log/strongswan.charon.log {
                   time_format = %b %e %T
                   default = 2
                   append = no
                   flush_line = yes
               }
       }
}

从 strongswan 5 起,无论是 ikev1 还是 ikev2 协议都使用 ikev2 的 daemon:charon 来实现。也就是说不必再在 /etc/strongswan.conf 里配置 pluto 了。

duplicheck.enable = no 是为了你能同时连接多个设备,所以要把冗余检查关闭。

dns 就不说了。nbns 是 Windows 的 NetBIOS 名称服务器实现, wins 服务会请求的。实际上 NBNS 协议是一个标准协议,但问题是 Linux 不强制而 Windows 强制请求,你不定义就无法连接。所以对于 ipsec VPN 来说,这个就是只供 Windows 使用的。

下面的 filelog 定义了一个文本日志。ipsec 协议的各种实现似乎都没有显式定义文本日志(比如 racoon,strongswan 都没有),而是写入系统日志 syslog。那样不利于调试,所以显式定义一下。

  • default 是默认日志级别:-1,0,1,2,3,4。-1 是完全没有日志; 0 只告诉你连接建立、连接关闭; 1 只输出错误提示; 2 会输出错误、警告和调试信息; 3 会把连接传输的数据也打印; 4 则会把密钥内容这些敏感数据也打印。一般情况下,1 或 2 都可以。
  • append 是当你重启 strongswan 后,是接上次日志写,还是新建一个日志(上次的会被删除)。因为 strongswan 的日志太多了,所以用 no。
  • flush_line 是每产生一行日志,就写入到磁盘一次。防止突然断电,磁盘缓存数据丢失。

另外你还可以详细定义每个 strongswan 模块的日志级别,但是没什么必要,具体可见 LoggerConfiguration

启动 Strongswan

sudo systemctl enable strongswan.service
sudo systemctl start strongswan.service

注:如果是 openSUSE12.2 发行版,包中默认没有strongswan.service,需要用户到 /etc/init.d/ 目录下启动服务。

cd /etc/init.d/
sudo ipsec start

配置 Iptables 转发

使用 SuSEfirewall2

SuSEfirewall2 为系统默认防火墙,配置可以通过 YaST 修改,也可以通过直接编辑 /etc/sysconfig/SuSEfirewall2 来修改。

IPsec VPN 所需要的端口为 UDP 500 和 UDP 4500,在 /etc/sysconfig/SuSEfirewall2 里找到

FW_SERVICES_EXT_UDP=""

修改为

FW_SERVICES_EXT_UDP="500 4500"

需要启用路由功能,防火墙默认设置为未启用,将 /etc/sysconfig/SuSEfirewall2 中的

FW_ROUTE="no"

改为

FW_ROUTE="yes"

启用 NAT,将 /etc/sysconfig/SuSEfirewall2 中的

FW_MASQUERADE="no"

改为

FW_MASQUERADE="yes"

添加需要转发的网段 10.0.0.0/24 到配置中,在 /etc/sysconfig/SuSEfirewall2 里找到

FW_MASQ_NETS=""

修改为

FW_MASQ_NETS="10.0.0.0/24"

此外 IPsec VPN 可能还需要 启用 esp 或 ah,在 /etc/sysconfig/SuSEfirewall2 里找到

FW_SERVICES_EXT_IP=""

修改为

FW_SERVICES_EXT_IP="esp ah"

修改完成后重启防火墙

SuSEfirewall2 stop
SuSEfirewall2 start

使用 iptables

如果禁用了 SuSEfirewall2,也可以使用 iptables 来设置。

sudo iptables -A INPUT -p udp --dport 500 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 4500 -j ACCEPT
sudo iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -s 10.0.0.0/24 -j ACCEPT
sudo echo 1 > /proc/sys/net/ipv4/ip_forward

为了每次 VPS 启动不重新输入这些命令,我们做成了一个 Systemd 服务 strongswan-iptables.service。下载扔到 /etc/systemd/system,然后:

systemctl enable strongswan-iptables.service
systemctl start strongswan-iptables.service

即可运行上述命令。以后系统启动时也将自动运行上述命令。

openSUSE 客户端配置

strongswan 项目同时开发了 NetworkManager-strongswan,最新版本是 1.3。

安装 NetworkManager-strongswan

sudo zypper in NetworkManager-strongswan

GNOME 要安装 NetworkManager-strongswan-gnome

sudo zypper in NetworkManager-strongswan-gnome

KDE 要安装 NetworkManager-strongswan-kde4

sudo zypper in NetworkManager-strongswan-kde4

如果你的 strongswan 是 5.0.0 以上的话,你还要安装 strongswan-nm

sudo zypper in strongswan-nm

然后编辑 /etc/NetworkManager/VPN/nm-strongswan-service.name,替换

program=/usr/lib/ipsec/charon

为:

program=/usr/lib/ipsec/charon-nm

并重载 systemd 的全部系统服务

sudo systemctl --system daemon-reload

不然会出现 “vpn service 'strongswan' start timed out” 即 “signal of type SIGTERM received. Shutting down” 错误。因为 5 版的 strongswan 引入了一个 strongswan-nm 来避免与系统的 strongswan 冲突,而 openSUSE 的 NetworkManager-strongswan 的 systemd 服务有 bug(待修复),并不会去使用 strongswan-nm。

之后一定要重启 NetworkManager.service 服务:

sudo systemctl restart NetworkManager.service

不然你设置好了会发现无法保存私钥(private key)的密码,也不会弹出窗口,错误信息为:

 <error> [1370608229.893778] [nm-vpn-connection.c:1355] plugin_need_secrets_cb(): (f4f7fcdb-110b-4f80-8fc8-23934fc29a0c/strongswan) plugin NeedSecrets request #1 failed: dbus-glib-error-quark Rejected send message, 1 matched rules; type="method_call", sender=":1.3" (uid=0 pid=569 comm="/usr/sbin/NetworkManager --no-daemon ") interface="org.freedesktop.NetworkManager.VPN.Plugin" member="NeedSecrets" error name="(unset)" requested_reply="0" destination="org.freedesktop.NetworkManager.strongswan" (uid=0 pid=11246 comm="/usr/lib/ipsec/charon-nm ")

这是因为 NetworkManager 的 DBus 服务没有重载,不能识别 strongswan 的缘故。

配置要点如下:

  • 勾选系统连接,不然启动不了 daemon
  • 网关:你的服务器 URL 或 IP,必须和证书里面那个一样(证书里是 URL 这里就不能是 IP)
  • 证书:你的 CA 证书
  • 认证方式:证书/私钥
  • 证书:你的客户证书
  • 私钥:客户证书对应的私钥
  • 私钥密码:生成客户证书时让你输入的那个密码,没有就选不需要,否则选储存或总是询问
  • 勾选请求内部 IP 地址,不然你没有虚拟地址,tun 设备自然也没法为你中转流量
  • 勾选强制 UDP 封装,这是因为 strongswan 5 以后即使 ikev1 也是通过 ikev2 的 charon 后端通讯的。而 charon 有一个新的特性叫 MOBIKE,也就是手机端上的自动重连(只适用于使用证书的情况),这个特性是默认开启的。而开启了这个特性所有的流量都会走 4500 端口也就是 UDP。你不勾根本连不上。

其它客户端配置

其它 Linux

Chakra Linux

方法和openSUSE的大同小异,不过关键问题在于Chakra默认所有源中是没有Strongswan,这个时候各位可以借助CCR来实现安装,CCR中有三个包,分别是strongswan, networkmanager-strongswan, networkmanager-dispatcher-strongswan-systemd(目前三者由我自己维护,从AUR照抄,修改了其中一个依赖而已)。其中,第一个是主要的,第二个大家都知道,第三个是systemd服务。推荐客户端用户只需要安装前两个。(我的源中默认启用了所有的源,包括core, platform, desktop, apps, games, lib32, extra以及测试源和不稳定源,个人认为主要要启动extra源,因为需要到一些gtk库)

  • 编译安装两个主要包

ccr -S strongswan && ccr -S networkmanager-strongswan

(各位可以去喝喝茶,听听歌)

  • 下载strongswan源代码编译安装strongswan-nm,下载地址,下载到一个你知道的地方,我放到/home/source/目录下,解压后,开始编译strongswan-nm插件
# build charon with OpenSSL/NM Plugin
./configure --sysconfdir=/etc --prefix=/usr --libexecdir=/usr/lib \
   --disable-aes --disable-des --disable-md5 --disable-sha1 --disable-sha2 \
   --disable-fips-prf --disable-gmp --enable-openssl --enable-nm --enable-agent \
   --enable-eap-gtc --enable-eap-md5 --enable-eap-mschapv2
make
make install

完成安装后,注意/usr/lib/ipsec/目录下多出了一个charon-nm,这个就是我么需要的东西。下面的设置基本遵循玛丽苏的方式。

  • 编辑/etc/NetworkManager/VPN/nm-strongswan-service.name,替换
program=/usr/lib/strongswan/charon

为:

program=/usr/lib/ipsec/charon-nm
  • 后面的步骤依照openSUSE中“并重载 systemd 的全部系统服务”
  • NetworkManager 的配置要点同 openSUSE
  • 补充:这个时候你的客户端应该能够连接了,如果不能,首先看看防火墙策略,如果还是不行,你可以试试先随便连接一个 VPN ,然后断开再连自己的 strongswan

其他 Linux 发行版参考 openSUSE 配置。

iOS

把 CA 证书和之前做好的 pkcs12(.p12)发邮件给自己。在 iOS 上收邮件,导入两者。然后新建 IPSec VPN:

  • 服务器,和 openSUSE 的要求一样,都是 IP 或都是 URL
  • 账户和密码写 ipsec.secrets 里 XAUTH 前后的那两个
  • 如果要使用证书,证书选刚才的那个。否则可以不使用证书,输入 ipsec.secrets 里设置的 PSK 密码。

Android

IPSec Xauth PSK

我的 Jelly Bean 是有这个的,设置 VPN 之前 JB 要求你必须设置锁屏密码或者 PIN 码。

主要还是:

  • 服务器,同上
  • IPSec 预共享密钥:写 ipsec.secrets 里 PSK 后面的那个密码。

然后登入时还是用 XAUTH 前后的那两个做用户名密码。

"strongSwan VPN Client" for Android 4.0 (ICS)+

这是官方自己出的客户端,Google Play 里就有。

把之前做好的 pkcs12 发邮件给自己。实际上 pkcs12 里就包含了 CA 证书,iOS 是有 bug 才必须明确要求导入 CA 证书(鄙视之)。Android 不用。直接在 GMail 里点击就会提示你导入。

然后打开官方客户端,新建方案:

  • Gateway 就是服务器,同上
  • Type 选 IKEv2 Certificate
  • User certificate 选你刚才导入的
  • 取消自动选择 CA 证书,然后在用户证书里选你刚才从 pk12 导入的

Windows XP/Vista

注意: XP/Vista 本身不支持纯 IPsec 连接。如果使用 L2TP/IPsec 模式,使用证书会 fallback 到 iOS_cert 这个连接类型,使用预共享密码会 fallback 到 android-xauth-psk 这个连接类型。

使用 Shrew Soft VPN Client

下载:https://www.shrew.net/download/vpn

安装后打开,选「Add」:

  • 「General」选项卡下,把「Host Name or IP address」添好
  • 「Authorization」选项卡下:
    • 「Authorization Method」选「Mutual PSK + XAuth」
    • 「Local Identity」的「Identification Type」选「IP Address」
    • 「Credentials」下面「Pre Shared Key」里输入 PSK 密码
  • 「Phrase 1」,「Exchange Type」选「Main」
  • 「Phrase 2」,「PFS Exchange」选「auto」

保存。连接时用户名密码是你的 XAUTH 用户名密码。

服务器端对应的配置是 android-xauth-psk 的连接类型。

Windows 7+

使用 Shrew Soft VPN Client 客户端:和上面 XP 的一样。

使用自带客户端(Agile):

导入证书:

  • 开始菜单搜索「cmd」,打开后输入 mmc(Microsoft 管理控制台)。
  • 「文件」-「添加/删除管理单元」,添加「证书」单元
  • 证书单元的弹出窗口中一定要选「计算机账户」,之后选「本地计算机」,确定。
  • 在左边的「控制台根节点」下选择「证书」-「个人」,然后选右边的「更多操作」-「所有任务」-「导入」打开证书导入窗口。
  • 选择刚才生成的 client.cert.p12 文件。下一步输入私钥密码。下一步「证书存储」选「个人」。
  • 导入成功后,把导入的 CA 证书剪切到「受信任的根证书颁发机构」的证书文件夹里面。
  • 打开剩下的那个私人证书,看一下有没有显示「您有一个与该证书对应的私钥」,以及「证书路径」下面是不是显示「该证书没有问题」。
  • 然后关闭 mmc,提示「将控制台设置存入控制台1吗」,选「否」即可。

至此,证书导入完成。

注意: 千万不要双击 .p12 证书导入!因为那样会导入到当前用户而不是本机计算机中,ipsec 守护精灵是访问不了它的。

建立连接:

  • 「控制面板」-「网络和共享中心」-「设置新的连接或网络」-「连接到工作区」-「使用我的 Internet 连接」
  • Internet 地址写服务器地址,注意事项同 openSUSE 的,都是 IP 或都是 URL。
  • 描述随便写。
  • 用户名密码写之前配置的 EAP 的那个。
  • 确定
  • 点击右下角网络图标,在新建的 VPN 连接上右键属性然后切换到「安全」选项卡。
  • VPN 类型选 IKEv2
  • 数据加密是「需要加密」
  • 身份认证这里需要说一下,如果想要使用 EAP-MSCHAPV2 的话就选择「使用可扩展的身份认证协议」-「Microsoft 安全密码」,想要使用私人证书认证的话就选择「使用计算机证书」。

调试

如果没有特殊需要,服务器端的日志就足够检测出绝大多数问题的来源。

我唯一需要在客户端上侦错的那次是 iOS 客户端。

日志阅读技巧

strongswan 的 charon daemon 启动后,会初始化并加载之前你定义好的 conn,这部分 log 是没有必要去读的。当然在你配置有问题时可能就有必要了,但当配置有问题的时候,systemctl start strongswan.service 会失败,systemctl status strongswan.service 就会指出你配置问题所在的行号(=。=)...

所以你只要去查找「added configuration 'windows7'」,这里 windows7 是你配置的最后一个 conn 的名称,然后从那里往下看就好了。

另外连接失败是会把连接状态从 CONNECTING 变为 DELETEING 的,DELETEING 又会刷一大堆日志,但那些日志都是没用的。

服务器端调试

/var/log/strongswan-charon.log 文件

Linux 调试

参照 strongswan 配置教学改 /etc/strongswan.conf,之后同服务器端调试。

iOS 调试

越狱安装 iFile。编辑 /etc/racoon/racoon.conf 文件,找到 #log debug; 字段,改成:

log debug;
path logfile "/var/log/racoon.log";

保存。

Android 调试

  • strongSwan 官方客户端提供了日志查看功能。
  • android 自带的 VPN 调试方法如下:

打开「终端模拟器」,输入 su,会弹出超级用户,允许。

cd /storage/sdcard0
logcat -f ./log.txt

然后用 Airdroid 等工具把 SD 卡中的 log.txt 传到电脑上,打开搜索 VPN 即可。

Windows 调试

微软 technet:VPN Troubleshooting Tools

扩展阅读

计费软件

  • FreeRadius:账户认证和计费
  • daloRadius:用户账单管理

参考:使用 StrongSwan 搭建 IKEv1 IKEv2 VPN服务器|莓玩没了。注:该文的 strongswan 配置仅供参考(有很多冗余配置)。

  • MySQL:账户管理后台数据库

参考:SDB:搭建LAMP服务器

参考文献

配置选项:

设备/操作系统特殊要求:

作者

注意: 不提供代架设和答疑服务,请勿私信。