3
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

SoftEther VPNの設定をAnsibleで更新する

はじめに

このところリモートワーク推進の流れでVPNの設定をいじることが増えてきました。
いちいち手動で変更するのは管理が大変なので、今回はSoftEther VPN/PacketiX VPNの設定をAnsibleで更新するようにしてみました。
検証した環境は商用ライセンスのPacketiX VPNですが、無償版のSoftEther VPNも同じと思われます。以下ではまとめてSoftEther VPNと呼びます。

環境

  • PacketiX VPN Server 4.0 (Version 4.29 Build 9680)
  • Ansible 2.7.1

作成するロール

Ansibleのロールとしてvpn_configを作成することにします。すなわち以下のようなディレクトリ構成を想定しています。

$ tree roles
roles
`-- vpn_config
    |-- files
    `-- tasks

設定ファイルの準備

SoftEther VPNの設定ファイルはサーバのバイナリと同じディレクトリにvpn_server.configというファイル名で存在します。
設定ファイルを一から準備するのは大変なので、このファイルをベースにAnsibleで同期したい設定ファイルを作っていきます。

設定ファイルのフォーマットは以下のようになっています。

declare root
{
   uint ConfigRevision 112
   bool IPsecMessageDisplayed true
   string Region JP
   bool VgsMessageDisplayed false

...

}

この中から設定したくない項目を削っていきます。削るべき項目としては

  • ConfigRevision: これは設定更新毎にサーバ側でインクリメントされる値なので、必ずしも同期の必要はないです。
  • declare DDnsClient{}keyLocalHostname: ホスト毎に違う値が生成されるので削っておきます。
  • declare LicenseManager{}: ライセンス情報です。これもJinja2で埋め込んでもいいですが、今回は除外して手動で設定することにしました
  • 各種統計情報: サーバ側で勝手にカウントアップしていくような値は除外します。具体的にはBroadcastBytes, BroadcastCount, UnicastBytes, UnicastCount, LastCommTime, LastLoginTime, NumLoginです。これらはそもそも設定不能なので、設定ファイルに残っていても悪さはしませんが、Ansible側の更新判定がやりにくいので削ります。

が考えられます。不要な項目については行ごと削除します。

できた設定ファイルをroles/vpn_config/files/vpn_server.config.masterとして保存しておきます。

設定チェックスクリプト

次に現在のサーバ設定と先ほど用意した設定が一致しているかどうかを判定するスクリプトを作ります。

roles/vpn_config/files/check_config.sh
#!/bin/sh
cd `dirname $0`

./vpncmd localhost:8888 /server /PASSWORD:xxx /CMD ConfigGet vpn_server.config.tmp

diff vpn_server.config.tmp vpn_server.config.master | grep "^>"
ret=$?

rm vpn_server.config.tmp

if [ $ret = 0 ]; then
    exit 1
else
    exit 0
fi

vpncmdはコマンドラインからサーバを操作するツールで、サーバのバイナリと同じところにあると思います。
このコマンドで現在のサーバ設定を取得してvpn_server.config.tmpに保存しています。
その後、diffコマンドでmasterのファイルと差分があるかを確認しています。

ここではサーバのパスワードxxxを平文で書いていますが、必要に応じてAnsible Vaultでの暗号化などをしてください。

設定スクリプト

実際にサーバ設定を反映するスクリプトです。

roles/vpn_config/files/set_config.sh
#!/bin/sh
cd `dirname $0`
./vpncmd localhost:8888 /server /PASSWORD:xxx /CMD ConfigSet vpn_server.config.master

先ほどのConfigGetもそうですが、ConfigSetは引数に/を含むパスを取れないようです。
なのであらかじめvpn_server.config.masterが存在するディレクトリにcdするようにしています。

Ansibleのタスク

最後にAnsibleのタスクです。

roles/vpn_config/tasks/main.yml
- name: send config
  copy:
      src  : "{{ item.src  }}"
      dest : "{{ item.dest }}"
      owner: root
      group: root
      mode : "{{ item.mode }}"
  with_items:
      - { src: 'vpn_server.config.master', dest: '/usr/local/vpnserver/vpn_server.config.master', mode: '0600' }
      - { src: 'check_config.sh'         , dest: '/usr/local/vpnserver/check_config.sh'         , mode: '0700' }
      - { src: 'set_config.sh'           , dest: '/usr/local/vpnserver/set_config.sh'           , mode: '0700' }

- name: check config
  command: /usr/local/vpnserver/check_config.sh
  register: check_config
  check_mode: no
  failed_when: no
  changed_when: 'check_config.rc != 0'

- name: debug config
  debug:
      var: check_config
  when: check_config is changed

- name: set config
  command: /usr/local/vpnserver/set_config.sh
  when: check_config is changed

send configで設定ファイルとスクリプトの転送、check configで設定変更が必要かどうかのチェック、set configで反映です。また、設定変更があった場合はdebug configが変更内容をダンプします。

まとめ

最終的なロールの構成は以下のようになりました。

$ tree roles
roles
`-- vpn_config
    |-- files
    |   |-- check_config.sh
    |   |-- set_config.sh
    |   `-- vpn_server.config.master
    `-- tasks
        `-- main.yml
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
3
Help us understand the problem. What are the problem?