概要
- VPN Gateの公開サーバに接続するDockerクライアント
- Dockerイメージの作成: クライアントもサーバも対応
前提
- OpenVPN バージョン2系
- Docker
alpine:3.12
イメージopenvpn
v2.4easy-rsa
v3.0
OpenVPNとは
- TLSを用いたVPN
openvpn
コマンドで簡単起動- 設定ファイルでも、コマンドオプションでも
- クライアントも、サーバも
- 認証方式: 共通鍵、公開鍵、ユーザ・パスワード
- ネットワーク:
- プロトコル: UDP、TCP
- インターフェース: TUN(レイヤ3)、TAP(レイヤ2)
物理ネットワーク: 拠点A --- インターネット --- 拠点B
を、
論理: 仮想プライベートネットワーク(AとB) --- インターネット
にする。ここでは特に、
論理: OpenVPNクライアント --- OpenVPNサーバ --- インターネット
同じプライベートネットワークに属する(ように見える)
- 互いにプライベートIPアドレスでアクセス
プロキシ
- インターネット側からはクライアントは見えない
- サーバのグローバルIPアドレスでのアクセス記録
OpenVPNクライアント: VPN Gateのサーバに接続する例
VPN Gate
- 筑波大学における学術研究として2013年から運営
- 公式サイト: https://www.vpngate.net/
- 世界各地の公開VPNサーバ: 誰でも参加可能なボランティア運営
- クライアントも無償で接続できる
VPNサーバを信用できなくても
- HTTPSサイトとの通信内容は、VPNサーバ管理者でも盗聴できない
- ブラウザ組み込みの認証局証明書のおかげ
- ドメイン名はバレる、どのページかはバレない
クライアントからの接続手順
- OpenVPN設定ファイルのダウンロード
- 公式サイトのサーバリスト表から1つ選ぶ
- Dockerイメージの作成
alpine
にopenvpn
をインストール
- Dockerコンテナ起動
- 1のファイルをマウント、読み込み
OpenVPN設定ファイルのダウンロード
- 国旗が縦に並んでいる表の各行がVPNサーバ
- 「OpenVPN設定ファイル」をクリック
- 数種類あるVPNのうち、OpenVPNの対応があるもの
- 右端の「スコア」などを参考程度に
OpenVPN設定ファイル
- プロトコル: UDPか、TCPか
- UDPの方が高速
- 接続先: ホスト名か、IPアドレスか
- IPアドレスは変わったら使えなくなる
- 通常、この組み合わせ4種類のファイルが用意されている
- 一般に継続利用なら、UDPでホスト名のもの
設定ファイルの内容
- ただのテキストファイル、編集不要
- クライアント設定
- 末尾にサーバの証明書あり
# 主な項目例
# クライアントとしてVPN Gateのサーバに接続する場合
dev tun
# プロトコル
proto udp
# サーバの場所
remote ホスト名かIPアドレス ポート番号
# 暗号のアルゴリズム
cipher AES-128-CBC
auth SHA1
Dockerイメージの作成: クライアントもサーバも対応
alpine:3.12
イメージからビルド
openvpn
,openvpn-doc
easy-rsa
: 公開鍵方式のとき、サーバ証明書作成に使う
FROM alpine:3.12
# 情報更新
RUN apk update
# インストール
RUN apk add man man-pages openvpn openvpn-doc easy-rsa
# ページャ、英語
ENV PAGER=less LANG=C
WORKDIR /etc/openvpn
# サンプルファイルへのリンク
RUN ln -s /usr/share/doc/openvpn/samples/sample-config-files/
CMD ["/bin/sh"]
# ビルド
image=my-openvpn
docker build --tag $image .
設定ファイル、コマンドオプション
- どちらも併用可能
設定ファイルのとき
--cd
: 設定ファイルのあるディレクトリに移動--config
: 設定ファイル指定- オプション先頭の
--
を除いた項目名と引数を1行ずつ列挙するだけ
サンプルの設定ファイル
/usr/share/doc/openvpn/samples/sample-config-files/
Dockerコンテナ起動: OpenVPNクライアント
- 例:
$PWD/conf/client.conf
: ダウンロードした設定ファイル
docker
コマンドの調整
--network host
: ホストモード
--cap-add=NET_ADMIN
: ホストのネットワーク変更権限付与- 無いとエラー:
ERROR: Cannot ioctl TUNSETIFF tun: Operation not permitted (errno=1)
- 無いとエラー:
--device=/dev/net/tun
: TUNネットワークデバイスが必要- 無いとエラー:
ERROR: Cannot open TUN/TAP dev /dev/net/tun: No such file or directory (errno=2)
- 無いとエラー:
- SELinux対応:
:z
オプションでマウント時のラベル調整--volume "$PWD/conf":/etc/openvpn/conf:z
- CentOS8 Podmanのとき、
--mount
でも可 --mount type=bind,src="$PWD/conf",dst=/etc/openvpn/conf,relabel=shared
image=my-openvpn
container=openvpn-client
docker run --rm -it --name $container \
--network host \
--cap-add=NET_ADMIN --device=/dev/net/tun \
--volume "$PWD/conf":/etc/openvpn/conf:z \
$image \
openvpn --cd /etc/openvpn/conf --config client.conf
(中略)
TUN/TAP device tun0 opened
TUN/TAP TX queue length set to 100
/sbin/ip link set dev tun0 up mtu 1500
/sbin/ip addr add dev tun0 local 10.211.1.81 peer 10.211.1.82
/sbin/ip route add サーバネットワーク via ローカル物理ルータ
/sbin/ip route add 0.0.0.0/1 via 10.211.1.82
/sbin/ip route add 128.0.0.0/1 via 10.211.1.82
WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this
Initialization Sequence Completed
これで、VPN Gateのサイトなどにアクセスすると、グローバルIPアドレスがサーバのものになっていることを確認できる。
ネットワーク確認
TUNデバイスができている
- ルーティングを仮想するデバイス(レイヤ3)
ip address show type tun
# 例
9: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 100
link/none
inet 10.211.1.81 peer 10.211.1.82/32 scope global tun0
10.
から始まるプライベートIPアドレス (例)peer
の右がサーバ側
ルーティングテーブルにTUNデバイス
ip route show
0.0.0.0/1 via 10.211.1.82 dev tun0
default via 物理ルータIP dev eno1 proto static metric 100
10.211.1.82 dev tun0 proto kernel scope link src 10.211.1.81
128.0.0.0/1 via 10.211.1.82 dev tun0
サーバグローバルIP via 物理ルータIP dev 物理デバイス
(中略)
0.0.0.0/1
と128.0.0.0/1
により、全通信がVPN経由へ
コンテナ停止で元に戻る
- TUNデバイスが消え、ネットワーク、ルーティングが元に戻る