PackerとAnsibleを使用してAmazon Linux 2にNATインスタンスを作成します。

April 11, 2023

Intro

AmazonLinux2 を使用して NAT インスタンスを設定しました。構成プロセスに Packer と Ansible を使用しました。

  • AmazonLinux2 を使用して NAT インスタンスを設定します。
  • Amazonlinux2 が選択する理由
    • Lambda は外部から開始される着信接続をサポートしていないため、アクティブモードで FTP をサポートしません。
    • ECS は、プライベート IP アドレスの静的割り当てを許可していません。
    • Gateway タイプであるため、NAT プライベートゲートウェイと組み合わせることで静的割り当てを実現することは可能ですが、外部ソースからの着信接続を受け入れることはできません。

技術要素

  • Packer
  • Ansible
    • iptables
      • CENTOS7(AmazonLinux2)では、デフォルトのファイアウォール管理システムはファイアウォールです。ただし、IPTables を紹介して、NAT インスタンスをセットアップします。

ファイル構造

$ tree .
.
├── ansible.cfg
├── bin
│   └── init.sh
├── inventory
│   └── hosts
├── packer-template
│   └── nat_instance.json
├── playbook
│   └── setup.yml
└── roles
    └── iptable
        └── tasks
            ├── main.yml
            └── templates
                ├── iptables-config.j2
                ├── nat_cidr.j2
                └── sysctl.conf

Packer とテンプレートファイルの実行

  • Execution Command
    • packer build packer-template/nat_instance.json
.
└── packer-template
   └── nat_instance.json
{
    "variables": {
        "aws_access_key": "{{env `AWS_ACCESS_KEY`}}",
        "aws_secret_key": "{{env `AWS_SECRET_KEY`}}"
    },
    "builders": [
        {
            "type": "amazon-ebs",
            "access_key": "{{user `aws_access_key`}}",
            "secret_key": "{{user `aws_secret_key`}}",
            "region": "ap-northeast-1",
            "ami_regions": [
                "ap-northeast-1"
            ],
            "associate_public_ip_address": true,
            "source_ami": "ami-0a3d21ec6281df8cb",
            "instance_type": "t3.micro",
            "ssh_username": "ec2-user",
            "ami_name": "nat-{{timestamp}}",
            "tags": {
                "Name": "nat-instance"
            },
            "ena_support": true,
            "enable_t2_unlimited": false
        }
    ],
    "provisioners": [
    {
      "type": "shell",
      "script": "./bin/init.sh",
      "pause_before": "60s"
    },
    {
      "type": "ansible-local",
        "inventory_file": "inventory/hosts",
        "playbook_file": "playbook/setup.yml",
        "role_paths": [
                "roles/iptable"
            ],
        "staging_directory": "/tmp/ansible-local",
        "extra_arguments": ["-vv"]
    }]
}

Ansible の準備

  • ファイル構成
.
├── ansible.cfg
├── bin
│   └── init.sh
└── inventory
   └── hosts

Install ansible

Ansible インストールは、 。/bin/init.shを実行することで実行できます

#!/bin/bash
sudo yum -y update
# ansible install
amazon-linux-extras install epel
amazon-linux-extras enable ansible2
amazon-linux-extras install ansible2

インベントリファイルの構成

inventory/hosts ファイルを配置します。

設定したサーバーからローカルで Ansible を実行するため、ターゲットとして「ローカル」を指定します。

[default]
127.0.0.1

構成ファイルを配置します

ansible.cfgファイルを配置します

このファイルは、Ansible の実行に使用されます。以下はサンプル構成です。

[defaults]

# Specify the Python interpreter
interpreter_python=/usr/bin/python3
# Location of the hosts file
inventory = inventroy/hosts
# Whether to validate host keys when connecting
host_key_checking = True
# Number of parallel processes to use for remote connections
forks=5
# Path to the log file
log_path=~/logs/ansible/ansible.log
# Color settings
nocolor=0
scp_if_ssh=True

Ansible Playbook を作成します

  • file Structure
.
├── playbook
│   └── setup.yml
└── roles
    └── iptable
        └── tasks
            ├── main.yml
            └── templates
                ├── iptables-config.j2
                ├── nat_cidr.j2
                └── sysctl.conf

Packer によって呼び出される Playbook/setup.yml ファイルを作成します。 iptables のロールを呼び出し、ルーティング後に出口時にソースアドレス/ポート変換を実行するチェーンを渡します。

---
- hosts: all
  become: yes
  become_user: root
  remote_user: ec2-user
  roles:
    - role: iptable
      vars:
        nat_cidr: 10.0.0.1/24

また、playbook から呼び出される iptables ロールの main.yml ファイルも書きます。主な構成は、iptables のインストールと必要な設定ファイルの構成です。

  • roles/iptable/tasks/main.yml
---
- name: Install iptables-service
  yum: name=iptables-services state=latest

- name: Enable port forwarding
  template: src="sysctl.conf" dest="/etc/sysctl.conf" owner=root group=root mode=0644

# IP tables
- name: Make iptables file
  template: src="{{ item }}.j2" dest="/etc/sysconfig/{{ item }}" owner=root group=root mode=0600
  with_items:
    - "nat_cidr"

# IP tables config
- name: Make iptables-config file
  template: src="iptables-config.j2" dest="/etc/sysconfig/iptables-config-nat" owner=root group=root mode=0600

- name: Install ftp command
  yum: name=ftp state=latest

- name: Install tcpdump command
  yum: name=tcpdump state=latest

- name: Install lftp command
  yum: name=lftp state=latest
  • 上記で使用したテンプレート・ファイルを書き込んでいきます。
    • roles/iptable/tasks/templates/iptables-config.j2
    • roles/iptable/tasks/templates/sysctl.conf
    • roles/iptable/tasks/templates/nat_cidr.j2

roles/iptable/tasks/templates/iptables-config.j2

IPTABLES_MODULES="nf_conntrack_ftp nf_nat_ftp"
IPTABLES_MODULES_UNLOAD="yes"
IPTABLES_SAVE_ON_STOP="no"
IPTABLES_SAVE_ON_RESTART="no"
IPTABLES_SAVE_COUNTER="no"
IPTABLES_STATUS_NUMERIC="yes"
IPTABLES_STATUS_VERBOSE="no"
IPTABLES_STATUS_LINENUMBERS="yes"

roles/iptable/tasks/templates/sysctl.conf

IPv4 フォワーディングと呼ばれる機能を有効にするには、「/proc/sys/net/ipv4/ip_forward」ファイルの内容を「1」に設定する。

net.ipv4.ip_forward=1

roles/iptable/tasks/templates/nat_cidr.j2

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s {{ nat_cidr }} -j MASQUERADE
COMMIT
*raw
:PREROUTING ACCEPT [0:0]
-A PREROUTING -p tcp --dport 21 -j CT --helper ftp
COMMIT

EC2 のネットワーク設定を構成するには

インスタンス構成で、NAT インスタンスの Elastic Network Interface (ENI)の宛先チェックを無効にします。

aws ec2 modify-instance-attribute \
  --no-source-dest-check \
  --instance-id ${INSTANCE_ID}

サーバーに接続して iptables を起動するには

Ansible を使って設定ファイルをデプロイし、iptables を再起動するには

# 設定ファイルをAnsibleで配布されているファイルで上書きする
sudo cp /etc/sysconfig/iptables-config-nat /etc/sysconfig/iptables
# 設定の永続化
sudo service iptables save
# サービスを再起動する
sudo systemctl restart iptables
Nifty tech tag lists from Wouter Beeftink