IaCLinuxNetworkPython

AnsibleでOpenVPNのインストールをコード化する

IaC

以前に紹介した以下の記事で、AWS上のAmazonLinux2にOpenVPNサーバを構築しました。

AWS上のEC2でOpenVPNサーバを構築する 
https://syachiku.net/ec2openvpn-1/

ただし、OpenVPNサーバを構築するには証明局や証明書の作成などのかなり多くの手順が必要となり複雑です。

そこで、構成管理ツールであるAnsibleを利用してOpenVPNの構築をコード化(IaC)してみました。

ansible-playbookのコマンド一発で簡単にOpenVPNサーバが構築できるようにします。

1. 前提

  • EC2上に素のAmazonLinux2のインスタンスは用意されている
  • 証明局とサーバ証明書、クライアント証明書は新規で作成する
  • 細かいansibleの利用方法については解説しません。

2. 構築処理の流れ

基本的には以下の記事と同じ手順で構築しています。

AWS上のEC2でOpenVPNサーバを構築する 
https://syachiku.net/ec2openvpn-1/

3. 作成したansible playbookについて

作成したansible playbookについて記載した後に、実際の構築手順について説明したいと思います。

3.1. ディレクトリ構成

/etc/ansible/以下のディレクトリは以下のようにしました。
localhostに対して実行するのでhostsファイルは不要です。 ベストプラクティスに沿って構築しているつもりです。

/etc/ansible/
├── ansible.cfg
├── hosts
├── roles
│   └── vpn
│       ├── files
│       │   ├── client.ovpn
│       │   └── server.conf
│       ├── handlers
│       │   └── main.yml
│       └── tasks
│           └── main.yml
├── site.yml
└── vars
    └── variables.yml

3.2. site.yml

こんな感じです。localhostに対してvpnのroleを実施しています。

- hosts: localhost
  become: yes
  become_user: root
  vars_files:
    - ./vars/variables.yml
  roles:
    - vpn

3.3. vars/variables.yml

変数を格納していますが、今回はたったこれだけです。今後の拡張を考えて一応変数にしました。

openvpn_easyrsa_path: /usr/share/easy-rsa/3

3.4. roles/vpn/tasks/main.yml

ここがタスクのメインですamazon-linux-extrasを利用する方法がパッと調べてもなかったのでshellで実行しています。

- name: enable amazon-linux-extras epel
  shell: "amazon-linux-extras install -y epel"

- name: install openvpn
  yum:
    name: openvpn
    enablerepo: amzn2extra-epel
    state: present

- name: install openvpn and easy-rsa
  yum:
    name: "{{ item }}"
    enablerepo: amzn2extra-epel
    state: present
    update_cache: yes
  with_items: [easy-rsa, openvpn]

- name: ensure /etc/openvpn/easy-rsa exists
  ansible.builtin.file:
    path: /etc/openvpn/easy-rsa
    state: directory
    mode: "0755"

- name: easyrsa init-pki
  ansible.builtin.command:
    cmd: "/usr/share/easy-rsa/3/easyrsa init-pki"
    chdir: /etc/openvpn/easy-rsa
    creates: /etc/openvpn/easy-rsa/pki

- name: easyrsa build-ca
  ansible.builtin.command:
    cmd: "/usr/share/easy-rsa/3/easyrsa build-ca nopass"
    chdir: /etc/openvpn/easy-rsa
    creates: /etc/openvpn/easy-rsa/pki/ca.crt
  environment:
    EASYRSA_BATCH: "yes"

- name: easyrsa gen-dh
  ansible.builtin.command:
    cmd: "/usr/share/easy-rsa/3/easyrsa gen-dh"
    chdir: /etc/openvpn/easy-rsa
    creates: /etc/openvpn/easy-rsa/pki/dh.pem

- name: easyrsa build-server-full server nopass
  ansible.builtin.command:
    cmd: "/usr/share/easy-rsa/3/easyrsa build-server-full server nopass"
    chdir: /etc/openvpn/easy-rsa
    creates: /etc/openvpn/easy-rsa/pki/issued/server.crt

- name: easyrsa build-client-full client nopass
  ansible.builtin.command:
    cmd: "{{ openvpn_easyrsa_path }}/easyrsa build-client-full client nopass"
    chdir: /etc/openvpn/easy-rsa
    creates: /etc/openvpn/easy-rsa/pki/issued/client.crt

- name: openvpn --genkey --secret /etc/openvpn/easy-rsa/pki/ta.key
  ansible.builtin.command:
    cmd: openvpn --genkey --secret /etc/openvpn/easy-rsa/pki/ta.key
    creates: /etc/openvpn/easy-rsa/pki/ta.key

- name: copy files to /etc/openvpn/server
  ansible.builtin.copy:
    src: /etc/openvpn/easy-rsa/pki/{{ item }}
    dest: /etc/openvpn/{{ item | basename }}
    mode: "0640"
    remote_src: yes
  loop:
    - ca.crt
    - dh.pem
    - ta.key
    - issued/server.crt
    - private/ca.key
    - private/server.key

- name: copy files for client to /home/ec2-user
  ansible.builtin.copy:
    src: /etc/openvpn/easy-rsa/pki/{{ item }}
    dest: /home/ec2-user/{{ item | basename }}
    mode: "0666"
    remote_src: yes
  loop:
    - ca.crt
    - ta.key
    - issued/client.crt
    - private/client.key

- name: copy openvpn config file
  copy: 
    src: server.conf
    dest: /etc/openvpn/server.conf
    owner: root
    group: root
    mode: 0644
  notify: vpn restart

- name: copy openvpn client ovpn file
  copy: 
    src: client.ovpn
    dest: /home/ec2-user/client.ovpn
    owner: root
    group: root
    mode: 0644

- name: enable ipv4.ip_forward
  sysctl:
    name: net.ipv4.ip_forward
    value: '1'
    state: present
    sysctl_set: yes
    reload: true

- name: start and enable openvpn
  ansible.builtin.service:
    name: "openvpn@server"
    state: started
    enabled: yes

3.5. roles/vpn/handlers/main.yml

OpenVPNサーバの再起動コマンドです。

- name: vpn restart
  shell: systemctl restart openvpn@server

3.6. roles/vpn/files

  • server.conf
    • push routeやDNSなどの設定は適宜変更してください。
    • 443ポートでVPN接続するようにしています。
port 443
proto tcp
dev tun
ca ca.crt
cert server.crt
key server.key  # This file should be kept secret
dh dh.pem
server 192.168.10.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "route 10.1.0.0 255.255.0.0"
push "dhcp-option DNS 10.1.100.4"
push "dhcp-option DNS 10.1.200.144"
keepalive 10 120
tls-auth ta.key 0 # This file is secret
cipher AES-256-CBC
persist-key
persist-tun
status openvpn-status.log
log         openvpn.log
log-append  openvpn.log
verb 3
explicit-exit-notify 0
  • client.ovpn
    • remoteのxx.xx.xx.xxは後でVPNサーバのPublicIPに手動で変更します
client
dev tun
proto tcp
remote xx.xx.xx.xx 443
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client.crt
key client.key
remote-cert-tls server
tls-auth ta.key 1
cipher AES-256-CBC
verb 3

4. 結果としてできるもの

  • AmazonLinux2のOpenVPNサーバがインストールされ、証明書関連もセットアップがされて、OpenVPNサービスが起動します。
  • クライアント(PC)で利用する証明書と設定ファイル(ひな形)が作成されて/home/ec2-user/に配置されます

5. OpenVPNの構築の実施

5.1. ansibleのインストール

ansibleのインストール方法については以下を参考にして下さい。簡単です。

EC2インスタンスとして構築したAmazonLinux2へAnsibleをインストール(yum) 
https://syachiku.net/amazonlinux2-ansible-install/

5.2. ansible-playbookの実行

ansible-playbookを実行してOpenサーバを構築します。 全部で5分くらいかかります。

# ansible-playbook /etc/ansible/site.yml

PLAY [localhost] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]
.
(略)
.
RUNNING HANDLER [vpn restart] **************************************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=18   changed=17   unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

5.3. AWS側設定

AWSインスタンス側で設定変更をします。

5.4. OpenVPNクライアント設定

/home/ec2-user/に配置されている証明書と設定ファイルをPC側にダウンロードします。

サーバ側のPubluc IPアドレスを確認して、設定ファイル(client.ovpn)の接続先を書き換えます。

OpenVPNクライアントのインストールや設定を行います。
 https://syachiku.net/ec2openvpn-1/#toc15

5.5. 接続確認

最後にVPNサーバに接続できる事を確認します。

6. まとめ

Ansibleを利用してAmazonLinux2にOpenVPN環境をかなり簡単に構築することができるようになりました。

私は普段はChefを利用していて、今回はじめて本格的にAnsibleを利用してみましたが、chefよりも使いやすいかもしれませんね。

次はせっかくAWSで構築していますので、最後の仕上げとしてCloudFormationと今回のAnsible Playbookを組み合わせてEC2の作成からサーバ構築までを自動化してみたいと思います。

ansibleの学習には以下の書籍を利用しています。かなり分かりやすくてオススメです。

Ansible実践ガイド 第3版 impress top gearシリーズ

Ansible実践ガイド 第3版 impress top gearシリーズ

北山 晋吾, 佐藤 学, 塚本正隆, 畠中幸司, 横地 晃
3,366円(09/22 02:48時点)
発売日: 2019/10/18
Amazonの情報を掲載しています

追記

以下の記事で最終的にCloudFormationとAnsibleを組み合わせてみました。

CloudFormationとAnsibleでEC2インスタンス構築時にOpenVPN構築してみた。
https://syachiku.net/cloudformation-ansible-userdata/

AWSを効率的に学習する方法

私がAWSを学習するために使った学習材料は「Udemy」だけです。

まずは座学を行ってAWSプラクティショナー もしくは ソリューションアーキテクト試験を取得することを目標にしました。

具体的にはUdemyで以下の2つの商材を購入して学習しました。AWS公式が提供している模擬試験も受けていません。

Udemyは世界最大級のオンライン学習プラットフォームで、世界中の学びたい人と教えたい人をオンラインでつなぐサービスです。 Udemyは米国Udemy,Inc.が運営するプラットフォームで日本ではベネッセが事業パートナーとして協業をしています。 C2C(consumer to consumer)により生まれる豊富で多彩な講座により個人の学習ニーズに応じた学びをみつけることができます。

これだけでOK! AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座(SAA-C02試験対応版)
【SAA-C02版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集(6回分390問)

今回は以上となります。

コメント

タイトルとURLをコピーしました