はじめに
頭悪い内容の記事で申し訳ありません。
とあるdockerホスト側にIPsecトンネルを張っていたのですが、Container側からの通信をdockerホスト側のIPsecトンネルに流すにはどうすれば良いのか悩んだので記事にしておきます。知ってる人には簡単なことかもしれませんが・・・
サーバ同士を接続するsite-to-siteなVPNの接続方法についてはたくさん記事はありますが、ひねった感じの記事が無かったので悩むことになりました。
今回の構成
今回の構成は以下の通り。
某VPSの中にZabbix環境をdocker Containerとして実装しています。ちなみに使用しているzabbix-dockerは以下のものです。
基本的にzabbixは同一LAN内で使用することがほぼ前提条件になると思いますが(zabbix proxyを使用する方法はありますが今回はなしでお願いします)、今回はIPsecで担保しています。
で、今回の場合、dockerホスト側にIPsecトンネルを張ることにしました。使用したパッケージはstrongswanです。
設定内容
以下のようなconfigを用意しました。
# ipsec.conf - strongSwan IPsec configuration file
# basic configuration
config setup
charondebug="all"
uniqueids=yes
strictcrlpolicy=no
# Add connections here
conn mikrotik-to-linux
keyexchange=ikev2
mobike=no
keyingtries=%forever
authby=secret
auto=start
type=tunnel
left=%defaultroute
leftid=<VPSのEIP>
leftsubnet=10.15.0.0/16
right=<接続先IPアドレス>
rightsubnet=192.168.88.0/24
ike=aes256-sha2_256-modp3072!
esp=aes256-sha2_256-modp3072!
ikelifetime=3h
lifetime=1h
dpddelay=30
dpdtimeout=120
dpdaction=restart
forceencaps=yes
fragmentation=yes
compress=no
closeaction=restart
installpolicy=yes
/etc/ipsec.secrets
下記にあるPSK(共通鍵)は実際に使用していません。
# This file holds shared secrets or RSA private keys for authentication.
# RSA private key for this host, authenticating it to any other host
# which knows the public part.
<接続元外側IP> <接続先外側IP> : PSK "wIG8N2jrkrxo7uSP5DJvnIEb0Xd494hy"
接続確認
接続先については割愛。で実施にIPsecが張れているか確認する。
$ sudo ipsec status
Security Associations (1 up, 0 connecting):
mikrotik-to-linux[2]: ESTABLISHED 23 minutes ago, 2.xxx.xxx.xxx[2.xxx.xxx.xxx]...1.yyy.yyy.yyy[1.yyy.yyy.yyy]
mikrotik-to-linux{2}: INSTALLED, TUNNEL, reqid 2, ESP in UDP SPIs: c9012d78_i 05dc8810_o
mikrotik-to-linux{2}: 10.15.0.0/16 === 192.168.88.0/24
$ sudo ip xfrm policy
src 10.15.0.0/16 dst 192.168.88.0/24
dir out priority 379519
tmpl src 2.xxx.xxx.xxx dst 1.yyy.yyy.yyy
proto esp spi 0x05dc8810 reqid 2 mode tunnel
src 192.168.88.0/24 dst 10.15.0.0/16
dir fwd priority 379519
tmpl src 1.yyy.yyy.yyy dst 2.xxx.xxx.xxx
proto esp reqid 2 mode tunnel
src 192.168.88.0/24 dst 10.15.0.0/16
dir in priority 379519
tmpl src 1.yyy.yyy.yyy dst 2.xxx.xxx.xxx
proto esp reqid 2 mode tunnel
src 0.0.0.0/0 dst 0.0.0.0/0
socket in priority 0
src 0.0.0.0/0 dst 0.0.0.0/0
socket out priority 0
src 0.0.0.0/0 dst 0.0.0.0/0
socket in priority 0
src 0.0.0.0/0 dst 0.0.0.0/0
socket out priority 0
src ::/0 dst ::/0
socket in priority 0
src ::/0 dst ::/0
socket out priority 0
src ::/0 dst ::/0
socket in priority 0
src ::/0 dst ::/0
socket out priority 0
src 2.xxx.xxx.xxx/32 dst 1.yyy.yyy.yyy/32 proto udp sport 1701 dport 1701
dir out priority 366847
tmpl src 0.0.0.0 dst 0.0.0.0
proto esp spi 0x0f255f8e reqid 1 mode transport
src 1.yyy.yyy.yyy/32 dst 2.xxx.xxx.xxx/32 proto udp sport 1701 dport 1701
dir in priority 366847
tmpl src 0.0.0.0 dst 0.0.0.0
proto esp reqid 1 mode transport
src 1.yyy.yyy.yyy/32 dst 2.xxx.xxx.xxx/32 proto udp sport 1701 dport 1701
dir fwd priority 366847
tmpl src 1.yyy.yyy.yyy dst 2.xxx.xxx.xxx
proto esp reqid 1 mode tunnel
ちなみに
strongswanってポリシーベースルーティングが設定されるんですな。
$ sudo ip route get 192.168.88.3
192.168.88.3 via 2.xxx.xxx.1 dev eth0 table 220 src 10.15.0.1 uid 0
cache
最初は、IPsec側のサブネット(leftsubnet
)を0.0.0.0/0
とかにすることも試してみたんですが、接続先の通信がVPS側に流れてしまって通信がおかしいことになったので(たぶん自分の勉強不足)、通信を制限した上で接続先に流す方法にしました。
これで良いかと言われれば、Container自体がdockerのネットワークブリッジの設定に従って自動的に採番されるためこのままでは、Containerを起動するたびにiptablesのルールを修正する必要があります。さすがにそれではあまりにも非効率なので、なんとか自動的にする方法を模索中です。