31.4. vpn RHEL システムロールを使用して証明書ベースの認証による IPsec メッシュ VPN を設定する
IPsec メッシュは、すべてのサーバーがセキュアで、他のすべてのサーバーと直接通信できる、完全に相互接続されたネットワークを作成します。これは、複数のデータセンターやクラウドプロバイダーにまたがる分散データベースクラスターまたは高可用性環境に適しています。各サーバー間で直接暗号化されたトンネルを確立することで、中央のボトルネックなしに通信をセキュアにすることができます。
認証には、認証局(CA)によって管理されるデジタル証明書を使用すると、安全性が高く、スケーラブルなソリューションが提供されます。メッシュの各ホストは、信頼できる CA によって署名された証明書を表示します。このメソッドは、強力な検証可能な認証を提供し、ユーザー管理を簡素化します。アクセスは CA で一元的に付与または取り消でき、Libreswan は、証明書失効リスト(CRL)に対して各証明書をチェックし、証明書がリストに表示されている場合はアクセスを拒否することで、これを強制します。
vpn RHEL システムロールを使用すると、証明書ベースの認証による管理対象ノード間の VPN メッシュの設定を自動化できます。
前提条件
- コントロールノードと管理対象ノードの準備が完了している。
- 管理対象ノードで Playbook を実行できるユーザーとしてコントロールノードにログインしている。
-
管理対象ノードへの接続に使用するアカウントに、そのノードに対する
sudo権限がある。 各管理対象ノード用に PKCS #12 ファイルを用意した。
各ファイルには次のものを含めます。
- サーバーの秘密鍵
- サーバー証明書
- CA 証明書
- 中間証明書 (必要な場合)
-
ファイル名は
<managed_node_name_as_in_the_inventory>.p12とします。 - ファイルは Playbook と同じディレクトリーに保存します。
サーバー証明書には次のフィールドを含めます。
-
Extended Key Usage (EKU) を
TLS Web Server Authenticationに設定します。 - コモンネーム (CN) またはサブジェクト代替名 (SAN) を、ホストの完全修飾ドメイン名 (FQDN) に設定します。
- X509v3 CRL ディストリビューションポイントには、証明書失効リスト(CRL)の URL が含まれます。
-
Extended Key Usage (EKU) を
手順
~/inventoryファイルを編集し、cert_name変数を追加します。managed-node-01.example.com cert_name=managed-node-01.example.com managed-node-02.example.com cert_name=managed-node-02.example.com managed-node-03.example.com cert_name=managed-node-03.example.comcert_name変数は、各ホストの証明書で使用されるコモンネーム (CN) フィールドの値に設定します。通常、CN フィールドは完全修飾ドメイン名 (FQDN) に設定します。機密性の高い変数を暗号化されたファイルに保存します。
vault を作成します。
$ ansible-vault create ~/vault.yml New Vault password: <vault_password> Confirm New Vault password: <vault_password>ansible-vault createコマンドでエディターが開いたら、機密データを<key>: <value>形式で入力します。pkcs12_pwd: <password>- 変更を保存して、エディターを閉じます。Ansible は vault 内のデータを暗号化します。
次の内容を含む Playbook ファイル (例:
~/playbook.yml) を作成します。- name: Configuring VPN hosts: managed-node-01.example.com, managed-node-02.example.com, managed-node-03.example.com vars_files: - ~/vault.yml tasks: - name: Install LibreSwan ansible.builtin.package: name: libreswan state: present - name: Identify the path to IPsec NSS database ansible.builtin.set_fact: nss_db_dir: "{{ '/etc/ipsec.d/' if ansible_distribution in ['CentOS', 'RedHat'] and ansible_distribution_major_version is version('8', '=') else '/var/lib/ipsec/nss/' }}" - name: Locate IPsec NSS database files ansible.builtin.find: paths: "{{ nss_db_dir }}" patterns: "*.db" register: db_files - name: Initialize IPsec NSS database if not initialized ansible.builtin.command: cmd: ipsec initnss when: db_files.matched == 0 - name: Copy PKCS #12 file to the managed node ansible.builtin.copy: src: "~/{{ inventory_hostname }}.p12" dest: "/etc/ipsec.d/{{ inventory_hostname }}.p12" mode: 0600 - name: Import PKCS #12 file in IPsec NSS database ansible.builtin.shell: cmd: 'pk12util -d {{ nss_db_dir }} -i /etc/ipsec.d/{{ inventory_hostname }}.p12 -W "{{ pkcs12_pwd }}"' - name: Remove PKCS #12 file ansible.builtin.file: path: "/etc/ipsec.d/{{ inventory_hostname }}.p12" state: absent - name: Opportunistic mesh IPsec VPN with certificate-based authentication ansible.builtin.include_role: name: redhat.rhel_system_roles.vpn vars: vpn_connections: - opportunistic: true auth_method: cert policies: - policy: private cidr: default - policy: private cidr: 192.0.2.0/24 - policy: clear cidr: 192.0.2.1/32 vpn_manage_firewall: true vpn_manage_selinux: trueサンプル Playbook で指定されている設定は次のとおりです。
opportunistic: true-
複数ホスト間のオポチュニスティックメッシュを有効にします。
policies変数は、暗号化する必要があるサブネットとホストトラフィックを暗号化し、どれがプレーンテキスト接続を使用するかを定義します。 auth_method: cert- 証明書ベースの認証を有効にします。これを行うには、インベントリーで各管理対象ノードの証明書のニックネームを指定する必要があります。
policies: <list_of_policies>Libreswan ポリシーを YAML リスト形式で定義します。
デフォルトのポリシーは
private-or-clearです。これをprivateに変更するには、上記の Playbook に、デフォルトのcidrエントリーに応じた適切なポリシーを含めます。Ansible コントロールノードが管理対象ノードと同じ IP サブネットにある場合は、Playbook の実行中に SSH 接続が失われるのを防ぐために、コントロールノードの IP アドレスに
clearポリシーを追加します。たとえば、メッシュを192.0.2.0/24サブネット用に設定する必要があり、コントロールノードが IP アドレス192.0.2.1を使用する場合、Playbook に示されているように、192.0.2.1/32のclearポリシーが必要です。ポリシーの詳細は、Libreswan がインストールされているシステム上の
ipsec.conf(5)man ページを参照してください。vpn_manage_firewall: true-
ロールにより、管理対象ノード上の
firewalldサービスで必要なポートを開くことを指定します。 vpn_manage_selinux: true- ロールにより、IPsec ポートに必要な SELinux ポートタイプを設定することを指定します。
Playbook で使用されるすべての変数の詳細は、コントロールノードの
/usr/share/ansible/roles/rhel-system-roles.vpn/README.mdファイルを参照してください。Playbook の構文を検証します。
$ ansible-playbook --ask-vault-pass --syntax-check ~/playbook.ymlこのコマンドは構文を検証するだけであり、有効だが不適切な設定から保護するものではないことに注意してください。
Playbook を実行します。
$ ansible-playbook --ask-vault-pass ~/playbook.yml
検証
メッシュ内のノードで、別のノードに ping を送信して接続をアクティブ化します。
[root@managed-node-01]# ping managed-node-02.example.com接続がアクティブであることを確認します。
[root@managed-node-01]# ipsec trafficstatus 006 #2: "private#192.0.2.0/24"[1] ...192.0.2.2, type=ESP, add_time=1741938929, inBytes=372408, outBytes=545728, maxBytes=2^63B, id='CN=managed-node-02.example.com'