VPNクライアントのホストをAnsibleで操作してみよう

# はじめに
多拠点でのサーバの管理を考えた時に、利用する環境によってはネットワーク構成をしっかり見る必要があるなと考えました。
その時に、監視はNewRelic等を利用してサーバからのPush通知で実現できます。
一方で操作をするためには、外部からのアクセスの仕組みが必要となります。
しかし、セキュリティを考えるとSSHのポートを許可するのは避けたいので、VPN接続でのアクセスが望ましいと考えました。
また、今回はL2TP/IPSecではなく、Twitter等でPPTPがトレンドに上がっている気配がありましたので、PPTPを利用します。

# 背景と目的
## 背景
- 多拠点やマルチクラウド、マルチホスティングの様な環境の場合、VPN接続を自前で用意するケースがある
- 仮想/物理アプライアンスを準備・管理するのは設備、人的コストが掛かる

多拠点に物理のVPNルータや仮想のVyOSばらまいても、だれもが管理できるでものはないと考えられます。
その為、ネットワーク部分を極力簡素化して、サーバ側でVPNを巻き取ることで管理を省力化していきます。

## 目的
VPNクライアントをLinuxサービスとして動作させ、VPNサーバへ「自動的に再接続」することでスター型VPN網を構築し、VPNサーバ側にいるホストから集中管理できるようにします。

# 手順
1.　PPTPクライアントの準備
PPTPクライアントのインストールと設定をします。
まずはPPTPのパッケージを入れます。

```ubuntu:PPTPパッケージインストール
sudo apt-get install pptp-linux
```

パッケージをインストールしたら、PPTPの設定の作成をします。
ユーザー名とパスワードは後ほど設定するサーバ側のものと同一にします。

```ubuntu:pptp設定作成コマンド
sudo pptpsetup --create VPN1 --server <VPN Server domain> --username <username> --password <password> --encrypt
```

2.　PPTPサーバの設定（参考）
PPTPサーバとして、今回はEdgeRouterを使います。
そんなにメジャーな箱物ルータではありませんが、VyattaからフォークしたOSなので個人的に使いやすかったりお手事な価格なので結構好きです。
いっぱいちゅき:heart:

今回はEdgeRouter XでPPTPサーバの設定をします。
MTUの値はフレッツ想定です。
Client IPプールはお使いの環境に合わせて書き換えてください。

```edgerouter:vpn設定
 vpn {
     pptp {
         remote-access {
             authentication {
                 local-users {
                     username <username> {
                         password <password>
                     }
                 }
                 mode local
             }
             client-ip-pool {
                 start 172.16.11.1
                 stop 172.16.11.250
             }
             mtu 1258
             outside-address 0.0.0.0
         }
     }
 }
```
なお、この設定はVyatta/VyOSでも同様に利用できますが、outside-addressはVyOS1.1.xでは0.0.0.0が使えないので、WAN側のアドレスを指定しましょう。

これだけだと繋がらないので、Firewall設定もします。
このルールはEdgeRouter向けのTCP/1723通信を許可するものとなります。

```edgerouter:firewall設定
 firewall {
     name WAN_LOCAL {
         rule 40 {
             action accept
             description PPTP
             destination {
                 port 1723
             }
             protocol tcp
         }
     }
 }
```

3.　PPTPクライアントからPPTPサーバへ接続
PPTPクライアントからPPTPサーバへ接続しましょう。
PPTP用のインターフェースアドレスは接続用のローカルアドレスと、リモートアドレスがあります。
今回はローカルアドレスに172.16.11.80を使って設定します。

```ubuntu:PPTP接続作成
sudo pppd call VPN1 updetach 172.16.11.80:172.16.11.81
```

ルーティングの設定もします。
これでPPTPサーバ側のネットワークへ接続できるようになります。

```ubuntu:PPTPルーティング設定
sudo ip route add 172.16.10.0/24 dev ppp0
```

ここまで出来たら、PPTPクライアントの設定を確認しましょう。

```ubuntu:Interface確認
#ifconfig ppp0
ppp0      Link encap:Point-to-Point Protocol
          inet addr:172.16.11.80  P-t-P:172.16.11.81  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1254  Metric:1
          RX packets:308 errors:0 dropped:0 overruns:0 frame:0
          TX packets:226 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3
          RX bytes:215236 (215.2 KB)  TX bytes:30122 (30.1 KB)
```

```ubuntu:経路確認
# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         10.9.108.253    0.0.0.0         UG    0      0        0 ens160
localnet        *               255.255.255.0   U     0      0        0 ens160
p1090118-ipngn1 10.9.108.253    255.255.255.255 UGH   0      0        0 ens160
172.16.10.0     *               255.255.255.0   U     0      0        0 ppp0
172.16.11.81    *               255.255.255.255 UH    0      0        0 ppp0
```

4.　PPTPサーバ側のホストからの制御
PPTPサーバ側に接続されたホストからAnsibleで制御してみます。
今回はつながることを確認するので、Dateの結果をファイルに書き込むPlaybookで試します。

```ansible:date.yml
- hosts: ubuntu
  user: administrator
  tasks:
    - name: Display Date
      shell: date >> date.txt
```

```ansible:Playbookの実行
# ansible-playbook test.yml -k
SSH password:

PLAY [ubuntu] ******************************************************************

TASK [Gathering Facts] *********************************************************
ok: [172.16.11.80]

TASK [Display Date] ************************************************************
changed: [172.16.11.80]

PLAY RECAP *********************************************************************
172.16.11.80               : ok=2    changed=1    unreachable=0    failed=0
```

5.　PPTPクライアントの自動再接続例
PPTPクライアントが切断された場合に備えて、再接続用のスクリプトをCronに仕込んでおきます。
このスクリプトはppp0の有無を判別して、ppp0がいなかったら再接続する簡単なものです。
pppdのプロセスを確実に止めるなど、もうちょっと改良の余地はあるかもしれません。

```ubuntu:pppd
#! /bin/sh
ifconfig ppp0 > /dev/null 2>&1
result=$?

if [ $result -ne 0 ]
 then
  pppd call VPN1 updetach 172.16.11.80:172.16.11.81 > /dev/null 2>&1
  ip route add 172.16.10.0/24 dev ppp0 > /dev/null 2>&1
fi
```

# まとめ/さいごに
　LinuxのPPTPクライアントを利用して、VPN接続、及びサーバ側からの制御ができることを確認できました。
　各遠隔地の管理対象機器があまり多くない状況であれば、比較的容易にリモート制御ができる設定と考えています。
　さすがに今使うならVPNはL2TP/IPSecの方が良いと考えられますが、多拠点構成の参考にしてみてください。