VyOSを使った拠点間通信（VPN）

#はじめに
最近転職したのだが、
転職先での最初の構築作業として
VyOSとCISCOを使って拠点間通信をしようとなった

ちなみに初VPN接続設定である
かなり苦労した

#参考にしたもの
IDCFさんの公開されているマニュアルを見ながら進めていく
[VyOSでのIPsecサイト間VPN接続ガイド](https://www.idcf.jp/help/cloud/guide/pdf/vyos_cloud.pdf?cl=rd_0413)

またVyOSのマニュアルも多少参考にした
[VyOS ユーザーガイド](https://wiki.vyos-users.jp/index.php/%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%AC%E3%82%A4%E3%83%89)

#使用する機器、バージョン
CISCO C841M IOS Version 15.5(3)

VyOS 1.1.5

#条件の確認

今回構築するネットワークの条件を確認する
まずはみんな大好きネットワーク図

![vyos-cisco.jpg](https://qiita-image-store.s3.amazonaws.com/0/259343/62f328f5-9af9-6ca7-baa8-83cb0a7a3051.jpeg)


環境としてはクラウドサーバーにVyOSをインストールし、
拠点に置いてあるCISCOルーターとVPN通信を行う

以下は最終的な各マシンのインターフェイス情報

■CISCOルーター(CISCO C841M)
VLAN1(Ethernet0/0,1,2,3) 10.1.1.1/24 (LAN側インターフェイス)
Ethernet0/5              1.1.1.1/30 (WAN側インターフェイス)

■VyOS(Version,1.1.5)
eth0 			10.200.0.10 (クラウドのプライベートIP)
eth1 			10.2.2.1 (クラウド内で作る別のLAN)
2.2.2.2(クラウドサーバーのグローバルIP)

#CISCOの設定
早速CISCOのルーターを設定をしていく。

なお今回はすべて手作業での設定になる。

```
Router> en
Router# conf t
Router(config)# interface Vlan1 //Vlan1はデフォルトで作られているはず
Router(config-if)# ip address 10.1.1.1 255.255.255.0 
Router(config-if)# ip nat inside 

Router(config)# interface GigabitEthernet0/5
Router(config-if)# ip address 1.1.1.1 255.255.255.252 
Router(config-if)# ip nat outside 

Router(config)# ip route 0.0.0.0 0.0.0.0 1.1.1.2 //ルーターの対向側出口へデフォルトルート設定

Router(config)# access-list 10 permit 10.1.1.0 0.0.0.255
Router(config)# ip nat inside source list 10 interface GigabitEthernet0/5 overload　

```

これでwanとの通信ができるようになった
次に、マニュアルを参考にしてVPN設定をしていく

```
Router(config)# crypto isakmp policy 1
Router(config-isakmp)# encr 3des
Router(config-isakmp)# hash md5
Router(config-isakmp)# authentication pre-share
Router(config-isakmp)# group 2
Router(config-isakmp)# lifetime 3600

Router(config)# crypto isakmp key xxxxx address 2.2.2.2　//『xxxxx』は好きなパスキーワードを入力。VyOS側も同じものを使用すること。

Router(config)# crypto isakmp nat keepalive 20

Router(config)# crypto ipsec transform-set myset esp-3des esp-md5-hmac
Router(cfg-crypto-trans)# mode tunnel

Router(config)# crypto identity cloudid
Router(config-crypto-identity)# fqdn cloud

Router(config)# crypto map myvpn 10 ipsec-isakmp
Router(config-crypto-map)# set peer 2.2.2.2
Router(config-crypto-map)# set security-association lifetime seconds 1800
Router(config-crypto-map)# set transform-set myset
Router(config-crypto-map)# set identity cloudid
Router(config-crypto-map)# match address 101

Router(config)# access-list 101 permit ip 10.1.1.0 0.0.0.255 10.2.2.0 0.0.0.255

Router(config)# interface GigabitEthernet0/5
Router(config-if)# crypto map myvpn
```

これでひとまずCISCO側の設定は終了。
続いてはVyOSの設定。

#VyOSの設定
使用するクラウドによってOSインストール方法が異なるため、
今回はインストールが完了し、SSHで接続した状態からの設定作業を記載をする。

まずは基本的な設定から

```
$ configure
# set interfaces ethernet eth0 description 'OUTSIDE'

# set interfaces ethernet eth1 address '10.2.2.1/24'
# set interfaces ethernet eth1 description 'INSIDE'
```
これでネットワークの条件は合ったため、
ここからVPNの設定を行っていく

```
\\firewallのルール作成
# set firewall name FW_RULE default-action 'drop'
# set firewall name FW_RULE rule 40 action 'accept'
# set firewall name FW_RULE rule 40 protocol 'esp'
# set firewall name FW_RULE rule 40 source address '1.1.1.1'

# set firewall name FW_RULE rule 41 action 'accept'
# set firewall name FW_RULE rule 41 destination port '500'
# set firewall name FW_RULE rule 41 protocol 'udp'
# set firewall name FW_RULE rule 41 source address '1.1.1.1'

# set firewall name FW_RULE rule 42 action 'accept'
# set firewall name FW_RULE rule 42 destination port '4500'
# set firewall name FW_RULE rule 42 protocol 'udp'

# set firewall name FW_RULE rule 43 action 'accept'
# set firewall name FW_RULE rule 43 destination port '1701'
# set firewall name FW_RULE rule 43 ipsec 'match-ipsec'
# set firewall name FW_RULE rule 43 protocol 'udp'

# set firewall name FW_RULE rule 100 action 'accept'
# set firewall name FW_RULE rule 100 source address '10.2.2.0/24'

# set firewall name FW_RULE rule 110 action 'accept'
# set firewall name FW_RULE rule 110 source address '10.1.1.0/24'

\\作成したfirewallのルールをインターフェイスに適用
# set interfaces ethernet eth1 firewall in name 'FW_RULE'
# set interfaces ethernet eth1 firewall local name 'FW_RULE'

\\natの設定
# set nat source rule 100 outbound-interface 'eth0'
# set nat source rule 100 source address '10.2.2.0/24'
# set nat source rule 100 translation address 'masquerade'

# set nat source rule 110 outbound-interface 'eth0'
# set nat source rule 110 source address '192.168.100.0/30'
# set nat source rule 110 translation address 'masquerade'

\\VPNセッションの設定
# set vpn ipsec esp-group ESP-G compression 'disable'
# set vpn ipsec esp-group ESP-G lifetime '1800'
# set vpn ipsec esp-group ESP-G mode 'tunnel'
# set vpn ipsec esp-group ESP-G pfs 'dh-group2'
# set vpn ipsec esp-group ESP-G proposal 1 encryption '3des'
# set vpn ipsec esp-group ESP-G proposal 1 hash 'md5'

# set vpn ipsec ike-group IKE-G dead-peer-detection action 'restart'
# set vpn ipsec ike-group IKE-G dead-peer-detection interval '15'
# set vpn ipsec ike-group IKE-G dead-peer-detection timeout '90'
# set vpn ipsec ike-group IKE-G ikev2-reauth 'no'
# set vpn ipsec ike-group IKE-G key-exchange 'ikev1'
# set vpn ipsec ike-group IKE-G lifetime '3600'
# set vpn ipsec ike-group IKE-G proposal 1 dh-group '2'
# set vpn ipsec ike-group IKE-G proposal 1 encryption '3des'
# set vpn ipsec ike-group IKE-G proposal 1 hash 'md5'

# set vpn ipsec ipsec-interfaces interface 'eth0' ←wanに向いてるインターフェイスを指定？「eth1」だとVPN接続はできなかった

# set vpn ipsec nat-networks allowed-network '0.0.0.0/0'
# set vpn ipsec nat-traversal 'enable'

# set vpn ipsec site-to-site peer 1.1.1.1 authentication id '@cloud'
# set vpn ipsec site-to-site peer 1.1.1.1 authentication mode 'pre-shared-secret'
# set vpn ipsec site-to-site peer 1.1.1.1 authentication pre-shared-secret 'xxxxx' ←好きなパスキーワードを入力。CISCOと同じものを使用。
# set vpn ipsec site-to-site peer 1.1.1.1 connection-type 'initiate'
# set vpn ipsec site-to-site peer 1.1.1.1 default-esp-group 'ESP-G'
# set vpn ipsec site-to-site peer 1.1.1.1 ike-group 'IKE-G'
# set vpn ipsec site-to-site peer 1.1.1.1 ikev2-reauth 'inherit'
# set vpn ipsec site-to-site peer 1.1.1.1 local-address '10.200.0.10'
# set vpn ipsec site-to-site peer 1.1.1.1 tunnel 1 allow-nat-networks 'disable'
# set vpn ipsec site-to-site peer 1.1.1.1 tunnel 1 allow-public-networks 'disable'
# set vpn ipsec site-to-site peer 1.1.1.1 tunnel 1 local prefix '10.2.2.0/24'
# set vpn ipsec site-to-site peer 1.1.1.1 tunnel 1 protocol 'gre'
# set vpn ipsec site-to-site peer 1.1.1.1 tunnel 1 remote prefix '10.1.1.0/24'

設定のコミット・セーブ、VPNのサービスを再起動
# commit
# save
# sudo /etc/init.d/ipsec restart
```

CISCO、VyOS両方の設定が間違えていなければ、これでVPNのセッションが張られているはず

```
■CISCO側で確認
router# show crypto isakmp sa
IPv4 Crypto ISAKMP SA
dst             src             state          conn-id status
1.1.1.1          2.2.2.2         QM_IDLE        2170 ACTIVE

IPv6 Crypto ISAKMP SA

router# show crypto ipsec sa
※表示項目が多いが、「inbound esp sas」「outbound esp sas」の二つの項目が空欄じゃなければOK

■VyOS側で確認
$ show vpn ike sa
Peer ID / IP                         Local ID / IP
------------                            -------------
1.1.1.1                              10.200.0.10

    State  Encrypt  Hash    D-H Grp  NAT-T  A-Time  L-Time
    -----  -------  ----    -------  -----  ------  ------
    up     3des     md5     2        yes    2397    3600

$ show vpn ipsec sa
Peer ID / IP                         Local ID / IP
------------                            -------------
1.1.1.1                              10.200.0.10

    Tunnel  State  Bytes Out/In   Encrypt  Hash    NAT-T  A-Time  L-Time  
    ------  -----  -------------  -------  ----    -----  ------  ------ 
    1       up     0.0/0.0        3des     md5     yes    1749    1800    

```


これでVPNセッションが張られたから完了かと思いきや、
まだ対向のLANに通信ができず状態

調べてみると、どうもVPNセッションが張られた際に作られるtunnelインターフェイスに対して、
更にルーティング設定を行う必要があるよう

#tunnelインターフェイスの設定
まずは、ネットワーク図を修正する
tunnelインターフェイスを足して以下のようなイメージ(tunnelのイメージが間違ってたらすいません)
 
![vyos-cisco-tunnel.jpg](https://qiita-image-store.s3.amazonaws.com/0/259343/192a0cc2-8ef6-28fe-bea4-f917ffc668f9.jpeg)


これからCISCO、VyOSそれぞれのtunnelインターフェイスに任意のIPアドレスを割り振り、
対向LANへのルーティングにtunnelインターフェイスを使うよう設定を行っていく

```
■CISCO側
Router(config)# interface Tunnel0
Router(config-if)# ip address 192.168.100.1 255.255.255.252
Router(config-if)# tunnel source 1.1.1.1
Router(config-if)# tunnel destination 2.2.2.2

Router(config)# ip route 10.2.2.0 255.255.255.0 Tunnel0

■VyOS側
# set interfaces tunnel tun0 address '192.168.100.2/30'
# set interfaces tunnel tun0 encapsulation 'gre'
# set interfaces tunnel tun0 local-ip '10.200.0.10'
# set interfaces tunnel tun0 mtu '1354'
# set interfaces tunnel tun0 multicast 'enable'
# set interfaces tunnel tun0 remote-ip '1.1.1.1'

# set protocols static interface-route 10.1.1.0/24 next-hop-interface 'tun0'

# commit
# save
```

これで問題なくVyOS－CISCO間での通信ができるようになった。

```
\\CISCO側
Router#ping 10.2.2.1
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.2.2.1, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/5/16 ms

\\VyOS側
# ping 10.1.1.1
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_req=1 ttl=255 time=2.43 ms
64 bytes from 10.1.1.1: icmp_req=2 ttl=255 time=2.42 ms
64 bytes from 10.1.1.1: icmp_req=3 ttl=255 time=2.38 ms
```

しかしまだこれでは終わらない。

この状態では、まだ対向LAN同士の通信はできない

それを解決するためには、それぞれのLAN内のマシンに、対向LAN向けのルーティングを設定する必要がある

例としてクラウド上のcentOSの設定を記載する
OSによってそれぞれルーティング設定を適宜行ってほしい

```
# vi /etc/sysconfig/network-scripts/ifcfg-eth1

DEVICE=eth1
TYPE=Ethernet
ONBOOT=yes

NM_CONTROLLED=no
BOOTPROTO=none
IPADDR=10.2.2.2
NETMASK=255.255.255.0
PEERDNS=no
PEERROUTES=no

# route add -net 10.1.1.0/24 gw 10.2.2.1 eth1
# route add -net 192.168.100.0/30 gw 10.2.2.1 eth1

# ping 10.1.1.1
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_req=1 ttl=255 time=2.43 ms
64 bytes from 10.1.1.1: icmp_req=2 ttl=255 time=2.42 ms
64 bytes from 10.1.1.1: icmp_req=3 ttl=255 time=2.38 ms


```

以上、これにてやっと対向LAN同士の通信もできるようになったかと

#VPNの永続的な接続
設定した内容はpingパケットを3回、15分おきに対向ルータに送信する

念のため、pingの結果を毎回適当なファイルに上書きしていく

```
$ vi /config/scripts/ping.sh

ping 10.100.60.1 -c 3 > /config/scripts/result.txt

$ chmod 755 /config/scripts/test.sh

$ configure
# set system task-scheduler task ping executable path /config/scripts/ping.sh
# set system task-scheduler task ping interval 15m

# commit
# save
```


#はまったところ
##VPNのセッションが張られない
参考にしたマニュアルそのままではVPNセッションができず、かなりのwebページを横断して設定を試してみたらなんとかできた

具体的につまづいたのは、
「CISCOのGUI操作で簡単にVPN接続できますよ」と書いてあるのができなかったり

CISCOにてVPN設定を作ったところで、WAN側インターフェイスにその設定を適用する手順が抜けており、
CISCOのページをみてそれに気付いたり

VyOSのIPSECを張るためのインターフェイス設定を自分が間違えていたり

##VPNのセッションが張られてもお互いに通信できない
これは本文でも書いたように、調べていく中でいろいろな設定をしてみたら徐々につながっていったという感じ

他の方が実施しているVPNの設定例を見てみると、CISCOにおいてPPPoEやDHCPで設定している場合は、今回の例まで作らなくても通信ができているようだった
しかしすべて手作業で行っていると、通信を行うまでに今回のようなtunnelの設定まで行う必要があった

対向LAN同士の通信においては、理論的には通るはずなのにおかしいと考えていたが、
拡張pingやtcpdumpの結果を見て何とかここまでこれた

##VPNセッションが時間で切れる
VPNを構築して少し時間が経ち、再度CISCOからVyOSに向けてpingを飛ばしてみたところ、つながらなくなっていた

IPsecのセッションは確かに張られているが、CISCOから通信できない
逆にVyOSからはpingが飛び、通信できる
VyOSから通信した後はCISCOからも通信できるようになった

VyOSにはVPNが時間で切れた後も再接続するように、
`DEAD PEER CONNECTION`という項目があるのだが、
これは現在、再接続には役立っていない様子

調べてみると、VPNが切れたら手動で再接続するように、というアナウンスがある

[リモートアクセスVPN接続が1時間毎に切れます。](https://www.faq.idcf.jp/app/answers/detail/a_id/834/related/1/session/L2F2LzEvdGltZS8xNTU2MDk2NzE5L3NpZC9mVWFlNnY0Tk52M1BzOHN3SUNSZHFMU2xuanB3eUhrdkJiclgwMU1TS0NSUkt2U1p2cmkzanhDZWZjUkJpVmJ4b0JSMFF1cEJWVFBjS2k1X3ZqQTNUeHpUWGdEek9jWVAlN0VUZjN4OUVEbzZXbkxsNXZseG96RlNVZyUyMSUyMQ==)

記事内ではwindows端末が対象と書いてあるが、
事象としては非常に近い気がする

今回は常時接続を前提としているので、VPNが切れるたびに手動で再接続なんて作業はやってられない

というわけでVyOSでcron的な動きで定期的にpingを送ればいいんじゃないかと思い、
設定した

VyOSにはcronは推奨されず、`Task scheduler`というものがあるため、
これを使ってみた