githubixx.harden_linux
ansible-role-harden-linux
このAnsibleロールは、私のブログシリーズ「Kubernetesを簡単にAnsibleで運用する - インスタンスを強化する」のために主に作成されました。しかしもちろん、Linuxを強化するために単独でも使用できます。以下の機能を持っています(いくつかはオプションです):
- 管理用の通常/デプロイユーザーを追加(例:Ansible用やSSHでのログイン用)
- APTの更新間隔を調整
UFW
ファイアウォールを設定し、デフォルトでSSHアクセスのみを許可(必要に応じて他のルール/許可されているネットワークを追加)- セキュリティ関連のsysctl設定を調整
sshd
の設定を調整(例:sshdパスワード認証を無効にする、sshdのルートログインを無効にする、sshd PermitTunnelを無効にする)sshguard
をインストールし、ホワイトリストを調整- ルートパスワードを変更
- 「ネットワーク時刻同期」(NTP)をインストール/設定(例:
openntpd
/ntp
/systemd-timesyncd
) systemd-resolved
の設定を変更
バージョン
すべてのリリースにタグを付け、セマンティックバージョニングを守るようにしています。このロールを使用したい場合は、最新のタグをチェックアウトすることをお勧めします。マスターブランチは基本的に開発用で、タグは安定したリリースを示します。ただし、一般的にマスターも良好な状態を保つことを心がけています。
変更履歴
変更履歴:
完全な CHANGELOG.md を参照してください。
最近の変更:
v8.2.0
- 機能
- Ubuntu 24.04のサポートを追加
v8.1.0
その他
- 暗号化されたパスワードを作成するために
ansible
ではなくmkpasswd
を使用することについてのコメントを更新 - Ubuntu: 自動削除タスクを追加
- GitHubワークフローを更新
- 暗号化されたパスワードを作成するために
MOLECULE
generic
Vagrantボックスの代わりにalvistack
を使用- 異なるIPアドレスを使用
v8.0.0
破壊的変更/機能
harden_linux_deploy_group
およびharden_linux_deploy_group_gid
変数を導入。どちらもオプションですが、harden_linux_deploy_user
が設定されている場合は少なくともharden_linux_deploy_group
を指定する必要があります。harden_linux_deploy_group
をroot
に設定すると、何も変更されません。harden_linux_deploy_user
をroot
に設定すると、何も変更されません。harden_linux_deploy_user
はオプションになりました。設定しない場合、ユーザーは設定されません。また、harden_linux_deploy_user_
で始まるすべての変数は、harden_linux_deploy_user
が指定された場合にのみ使用されます。さらに、harden_linux_deploy_user_home
変数が追加されました。harden_linux_deploy_user_shell
、harden_linux_deploy_user_home
、harden_linux_deploy_user_uid
、およびharden_linux_deploy_user_password
はオプションになりました。harden_linux_deploy_user
の$HOMEディレクトリは、harden_linux_deploy_user_home
が設定されている場合にのみ作成されます。
MOLECULE
- デプロイユーザー/グループの変更を反映するためにテストシナリオを更新
インストール
GitHubから直接ダウンロード(クローン前にAnsibleロールディレクトリに移動してください。ロールパスは
ansible-config dump | grep DEFAULT_ROLES_PATH
コマンドで確認できます):git clone https://github.com/githubixx/ansible-role-harden-linux.git githubixx.harden_linux
ansible-galaxy
コマンドを使ってAnsible Galaxyから直接ダウンロード:ansible-galaxy install role githubixx.harden_linux
次の内容で
requirements.yml
ファイルを作成(これによりGitHubからロールがダウンロードされ)て以下のコマンドでインストールします:ansible-galaxy role install -r requirements.yml
(必要に応じてversion
を変更):
---
roles:
- name: githubixx.harden_linux
src: https://github.com/githubixx/ansible-role-harden-linux.git
version: v8.1.0
ロール変数
以下の変数にはデフォルトがありません。group_vars
またはhost_vars
ディレクトリ内のファイルで指定する必要があります。例:これらの設定を特定のホストにのみ使用したい場合、そのホストのFQDNと同じ名前のファイル(例:host_vars/your-server.example.tld
)を作成し、正しい値で変数を書き込んでください。この変数をホストグループに適用したい場合、group_vars/your-group.yml
という名前のファイルを作成します。ここでyour-group
は、Ansibleのhosts
ファイルで作成したホストグループ名に置き換えてください(/etc/hostsと混同しないでください)。
root
ユーザーのパスワードを設定または変更したい場合は、harden_linux_root_password
変数を設定してください。これはオプションで、暗号化されたパスワードが必要です。Ansibleがパスワードを暗号化することはありません。暗号化されたパスワードの作成方法については、AnsibleのFAQを参照してください。Linuxでは、次のコマンドが最も信頼性が高いでしょう:
mkpasswd --method=sha-512
sud
をパスワードなしで実行できるユーザーをインストールするには、次の変数を設定します:
harden_linux_deploy_user: "a_username"
harden_linux_deploy_user_password: "a_password"
harden_linux_deploy_user_home: "/home/a_user"
harden_linux_deploy_user_uid: "9999"
harden_linux_deploy_user_gid: "9999"
harden_linux_deploy_user_shell: "/bin/bash"
harden_linux_deploy_user
は、リモートホストにログインするために使用するユーザーを指定します。前述のように、harden_linux
ロールはSSHでのrootユーザーのログインを無効にするため、別のユーザーが必要です。このユーザーには、Ansible(およびおそらくあなた自身)に必要な"sudo"権限が与えられます。
harden_linux_deploy_user_password
には、ユーザーの暗号化されたパスワードが保存されます。harden_linux_root_password
に関しても同様です。
ユーザーの$HOMEディレクトリは、harden_linux_root_password
で指定します。UIDとGIDは、harden_linux_deploy_user_uid
とharden_linux_deploy_user_gid
で設定します。注意:ユーザーがすでに存在するが、異なるホームディレクトリ、UID、および/またはGIDを持っている場合、上記の設定に従って変更されます!これはharden_linux_deploy_user_shell
にも適用され、このユーザーがログイン後に使用するシェルを指定します。
harden_linux_deploy_user_public_keys
は、リモートホストのデプロイユーザーの$HOME/.ssh/authorized_keys
に追加したい公開SSHキーのファイルリストを指定します。例:ここで/home/deploy/.ssh/id_rsa.pub
を指定すると、そのローカルファイル(Ansibleコントローラノード上)から内容がリモートホストのデプロイユーザーの$HOME/.ssh/authorized_keys
に追加されます。
harden_linux_optional_packages
(このロールのバージョンv6.0.0
より前はharden_linux_required_packages
と呼ばれていました)は、リモートホストにインストールする追加またはオプションパッケージを指定します。デフォルトではこの変数は指定されていません。例:
harden_linux_optional_packages:
- vim
対照的に、harden_linux_absent_packages
は、リモートホストのOSパッケージをアンインストールします。デフォルトでは、この変数は指定されていません。例:
harden_linux_absent_packages:
- vim
以下の変数にはデフォルトがあります。したがって、他の値が必要な場合にのみ変更する必要があります。ロールはデフォルトでいくつかのsshd
設定を変更します:
harden_linux_sshd_settings:
"^PasswordAuthentication": "PasswordAuthentication no" # パスワード認証を無効にします
"^PermitRootLogin": "PermitRootLogin no" # SSHのルートログインを無効にします
"^PermitTunnel": "PermitTunnel no" # tun(4)デバイス転送を無効にします
"^Port ": "Port 22" # sshdポートを設定します
個人的には、攻撃を受けやすいポートのため、デフォルトのSSHポートを変更します(ただし、ポートスキャナーはすぐにそのポートを特定できることに注意してください)。ポート設定を変更したい場合は、次のようにできます:
harden_linux_sshd_settings_user:
"^Port ": "Port 22222"
(^Port
の後の空白に注意してください!)。プレイブックは、harden_linux_sshd_settings
とharden_linux_sshd_settings_user
を組み合わせ、harden_linux_sshd_settings_user
の設定が優先され、harden_linux_sshd_settings
内の^Port
設定/キーを上書きします。
他のタスクでも同様のパターンが見られるため、これに関して述べたことが他の場合にも当てはまります。
次に、ファイアウォール/iptablesのデフォルト設定です。ファイアウォール/iptablesのルールと設定はUFWによって管理されます:
harden_linux_ufw_defaults:
"^IPV6": 'IPV6=yes'
"^DEFAULT_INPUT_POLICY": 'DEFAULT_INPUT_POLICY="DROP"'
"^DEFAULT_OUTPUT_POLICY": 'DEFAULT_OUTPUT_POLICY="ACCEPT"'
"^DEFAULT_FORWARD_POLICY": 'DEFAULT_FORWARD_POLICY="DROP"'
"^DEFAULT_APPLICATION_POLICY": 'DEFAULT_APPLICATION_POLICY="SKIP"'
"^MANAGE_BUILTINS": 'MANAGE_BUILTINS=no'
"^IPT_SYSCTL": 'IPT_SYSCTL=/etc/ufw/sysctl.conf'
"^IPT_MODULES": 'IPT_MODULES="nf_conntrack_ftp nf_nat_ftp nf_conntrack_netbios_ns"'
これらの設定は基本的に/etc/defaults/ufw
の値を変更します。デフォルト設定の1つまたは複数を上書きする場合、上のように同じキー(これはregexです)を指定し、新しい値を割り当てます:
harden_linux_ufw_defaults_user:
"^DEFAULT_FORWARD_POLICY": 'DEFAULT_FORWARD_POLICY="ACCEPT"'
先に説明したように、このプレイブックは、harden_linux_ufw_defaults
とharden_linux_ufw_defaults_user
を組み合わせます。この場合も、harden_linux_ufw_defaults_user
の設定が優先されます。
次に、harden_linux_ufw_rules
を使ってファイアウォールルールを指定できます。デフォルトでは、ポート22
でSSHトラフィックを許可します(プロトコルはtcp
):
harden_linux_ufw_rules:
- rule: "allow"
to_port: "22"
protocol: "tcp"
次のパラメータがデフォルト値(もしあれば)付きで利用可能です:
rule (デフォルトなし)
interface (デフォルト: '')
direction (デフォルト: 'in')
from_ip (デフォルト: 'any')
to_ip (デフォルト: 'any')
from_port (デフォルト: '')
to_port (デフォルト: '')
protocol (デフォルト: 'any')
log (デフォルト: 'false')
delete (デフォルト: 'false')
ルールはallow
、deny
、limit
、reject
の値を持つことができます。インターフェースはそのルールに対して設定します。方向(in
またはout
)はインターフェースによって値に依存します。from_ipはソースIPアドレス、from_portはソースポート、to_ipは宛先IPアドレス、to_portは宛先ポートを指定します。プロトコルはデフォルトでany
です。有効な値はtcp
、udp
、ipv6
、esp
、ah
、gre
、igmp
です。logはfalse
(デフォルト)またはtrue
のどちらかを取ります。新しい接続がこのルールに一致した場合、ログに記録されます。deleteはルールを削除するかどうかを指定します。以前に追加されたルールを削除する場合は重要です。単にharden_linux_ufw_rules
からルールを削除するだけでは不十分です!削除するためにはdelete
を使用する必要があります。
特定のネットワーク間でホストが通信できるようにすることもできます(ポート制限はなし):
harden_linux_ufw_allow_networks:
- "10.3.0.0/24"
- "10.200.0.0/16"
次に、harden_linux
ロールは一部のシステム変数(sysctl.conf / procファイルシステム)も変更します。これらの設定は、Googleが自社のGoogle Compute Cloud OSイメージに使用している推奨事項です(Google Cloud - カスタムイメージを構築するための要件およびCompute Engine用にインポートしたイメージを構成するを参照)。デフォルト設定は次のとおりです(これらの設定に満足している場合は、特に何もする必要はありませんが、動作するかどうかは確認することをお勧めします):
harden_linux_sysctl_settings:
"net.ipv4.tcp_syncookies": 1 # SYNフラッド防止を有効にします
"net.ipv4.conf.all.accept_source_route": 0 # ソースルーティングされたパケットを無視します
"net.ipv6.conf.all.accept_source_route": 0 # IPv6 - ICMPリダイレクトを無視します
"net.ipv4.conf.default.accept_source_route": 0 # ソースルーティングされたパケットを無視します
"net.ipv6.conf.default.accept_source_route": 0 # IPv6 - ソースルーティングされたパケットを無視します
"net.ipv4.conf.all.accept_redirects": 0 # ICMPリダイレクトを無視します
"net.ipv6.conf.all.accept_redirects": 0 # IPv6 - ICMPリダイレクトを無視します
"net.ipv4.conf.default.accept_redirects": 0 # ICMPリダイレクトを無視します
"net.ipv6.conf.default.accept_redirects": 0 # IPv6 - ICMPリダイレクトを無視します
"net.ipv4.conf.all.secure_redirects": 1 # 非GWホストからのICMPリダイレクトを無視します
"net.ipv4.conf.default.secure_redirects": 1 # 非GWホストからのICMPリダイレクトを無視します
"net.ipv4.ip_forward": 0 # ネットワーク間のトラフィックを許可しない
"net.ipv6.conf.all.forwarding": 0 # IPv6 - ネットワーク間のトラフィックを許可しない
"net.ipv4.conf.all.send_redirects": 0 # ネットワーク間のトラフィックを許可しない
"net.ipv4.conf.default.send_redirects": 0 # ネットワーク間のトラフィックを許可しない
"net.ipv4.conf.all.rp_filter": 1 # リバースパスフィルタリング - IPスプーフィング防止
"net.ipv4.conf.default.rp_filter": 1 # リバースパスフィルタリング - IPスプーフィング防止
"net.ipv4.icmp_echo_ignore_broadcasts": 1 # Smurf攻撃に参加しないようにICMPブロードキャストを無視します
"net.ipv4.icmp_ignore_bogus_error_responses": 1 # 無効なICMPエラーを無視します
"net.ipv4.icmp_echo_ignore_all": 0 # 無効なICMPエラーを無視します
"net.ipv4.conf.all.log_martians": 1 # スプーフィング、ソースルーティングされたパケット、およびリダイレクトパケットを記録します
"net.ipv4.conf.default.log_martians": 1 # スプーフィング、ソースルーティングされたパケット、およびリダイレクトパケットを記録します
"net.ipv4.tcp_rfc1337": 1 # RFC 1337に対する修正を実装
"kernel.randomize_va_space": 2 # mmapベース、ヒープ、スタック、およびVDSOページのアドレスをランダム化
"fs.protected_hardlinks": 1 # ToCToUレースからの保護を提供
"fs.protected_symlinks": 1 # ToCToUレースからの保護を提供
"kernel.kptr_restrict": 1 # カーネルアドレスの特定を困難にします
"kernel.perf_event_paranoid": 2 # perfをrootのみで利用可能にします
すべての設定を上書きすることができます。たとえば、harden_linux_sysctl_settings_user
という変数を作成することで上書きできます:
harden_linux_sysctl_settings_user:
"net.ipv4.ip_forward": 1
"net.ipv6.conf.default.forwarding": 1
"net.ipv6.conf.all.forwarding": 1
プレイブックのタスクの1つが、harden_linux_sysctl_settings
とharden_linux_sysctl_settings_user
を組み合わせ、harden_linux_sysctl_settings_user
の設定が優先されます。設定に関する詳細は、ロールのdefaults/main.yml
ファイルを参照してください。
UFWのロギングを有効にしたい場合は、以下を設定します:
harden_linux_ufw_logging: 'on'
可能な値はon
、off
、low
、medium
、high
、full
です。
次に「sshguard」の設定について。「sshguard」は、SSHに対するブルートフォース攻撃から保護します。自分自身を長時間ロックアウトしないように、IPまたはIP範囲をホワイトリストに追加できます。デフォルトでは基本的に「localhost」だけです:
harden_linux_sshguard_whitelist:
- "127.0.0.0/8"
- "::1/128"
NTPパッケージもインストール/設定できます。これはオプションです。デフォルトでは、systemd-timesyncd
の使用をお勧めします。また、ntp
パッケージも使用できます。ただし、openntpd
やsystemd-timesyncd
は、デフォルトでポートを開放しないという利点があります。ホストの時計を同期させるだけであれば、これで十分です。すべてのホストで同じ時間を持つことは、証明書の検証、etcd、データベース、暗号化など、多くのサービスにとって重要です。
harden_linux_ntp
の有効なオプションは次のとおりです:
- openntpd
- ntp
- systemd-timesyncd
openntpd
およびsystemd-timesyncd
はデフォルトでポートを開放しないため、ホストの時計を同期させるためにはこれらのいずれかで問題ありません。systemd-timesyncd
は、systemd
を使用するディストリビューションで既にインストールされています(基本的に現在のほとんどのLinux OSで真実です)。この場合、追加のパッケージは不要です。openntpd
を有効にするには、次のようにharden_linux_ntp
を設定します:
harden_linux_ntp: "openntpd"
openntpd
、ntpd
またはsystemd-timesyncd
の設定(次の段落を参照)。さらなるオプションについては、man 5 ntpd.conf
を参照してください。
ここでの「キー」は、置換したい設定の正規表現で、値は設定名と設定値です。例として、servers 0.debian.pool.ntp.org
の行をservers 1.debian.pool.ntp.org
に置き換えたい場合、正規表現(キー)は^servers 0
となります。
これは「server 0
で始まる行を検索し、行全体をservers 1.debian.pool.ntp.org
に置き換えます」となります。このように設定ファイル内の任意の設定を他の何かに置き換えることができます。いくつかの例:
harden_linux_ntp_settings:
"^servers 0": "servers 0.debian.pool.ntp.org"
"^servers 1": "servers 1.debian.pool.ntp.org"
"^servers 2": "servers 2.debian.pool.ntp.org"
"^servers 3": "servers 3.debian.pool.ntp.org"
注意:systemd-timesyncd
は合理的なコンパイル時のデフォルトを持ちます。そのため、設定を変更する必要は通常ありません(NTPサーバーさえも)。以下は単なる例であり、systemd-timesyncd
に対してharden_linux_ntp_settings
を指定する必要はありません。
systemd-timesyncd
の場合、設定ファイルは少し異なります。この場合、/etc/systemd/timesyncd.conf
のためのsystemdドロップインが/etc/systemd/timesyncd.conf.d/
に作成され、指定された設定が追加されます。
Debianの例:
harden_linux_ntp_settings:
"^#NTP=": "NTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org"
Ubuntuの例:
harden_linux_ntp_settings:
"^#NTP=": "NTP=ntp.ubuntu.com"
Archlinuxの例:
harden_linux_ntp_settings:
"^#NTP=": "NTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org"
harden_linux_files_to_delete
を使用して、ターゲットホストで存在しないべきファイルのリストを指定できます。例:
harden_linux_files_to_delete:
- "/root/.pw"
systemd-resolved
がDNS解決に使用されている場合、その動作はharden_linux_systemd_resolved_settings
で調整できます。デフォルトでは、この変数は指定されていません。systemdドロップイン構成が/etc/systemd/resolved.conf.d/99-override.conf
に作成され、そこに指定された設定が追加されます。
注意:/etc/systemd/resolved.conf
内に設定がすでに設定されている場合(例:DNS=8.8.8.8
)、以下にDNS=9.9.9.9
を設定すると、最終的な設定はDNS=8.8.8.8 9.9.9.9
になります。それを望まない場合は、まずその値を「解除」し、次に望む値を追加する必要があります。例:
harden_linux_systemd_resolved_settings:
- DNS=
- DNS=9.9.9.9
GoogleのDNSサーバー(8.8.8.8
、8.8.4.4
)は迅速なDNSルックアップを提供しますが、もちろん、Googleがあなたを監視する可能性があります。他のDNSサーバーを使用することは少なくとも考慮すべきことです。さらに、DNSリクエストを暗号化することも考えられます。systemd-resolved
がサポートしている方法の1つはDNSOverTLS
です。Quad9 (9.9.9.9/149.112.112.112)およびCloudflare (1.1.1.1/1.0.0.1)はDNSOverTLS
をサポートしています。
以下のsystemd-resolved
設定は、IPv4およびIPv6のためにQuad9とCloudflare DNSを設定します。設定DNSOverTLS=opportunistic
は、DNSサーバーがサポートしている場合にDNSOverTLS
を使用し、サポートされていない場合は通常の暗号化されていないDNSにフォールバックします(詳しくはresolved.conf.5を参照):
harden_linux_systemd_resolved_settings:
- DNS=
- DNS=9.9.9.9 1.1.1.1 2606:4700:4700::1111 2620:fe::fe
- FallbackDNS=
- FallbackDNS=149.112.112.112 1.0.0.1 2620:fe::9 2606:4700:4700::1001
- DNSOverTLS=
- DNSOverTLS=opportunistic
また、パッケージマネージャのキャッシュ動作も調整できます。たとえば、Ubuntuの場合:
# パッケージキャッシュを更新しない場合は"false"に設定
harden_linux_ubuntu_update_cache: true
# パッケージキャッシュの有効時間を設定
harden_linux_ubuntu_cache_valid_time: 3600
Archlinuxの場合:
# パッケージキャッシュを更新しない場合は"false"に設定
harden_linux_archlinux_update_cache: true
使用例プレイブック
ansible-galaxy install githubixx.harden_linux
でロールをインストールした場合、プレイブックにロールを含めることができます。以下の例をご覧ください:
- hosts: webservers
roles:
- githubixx.harden_linux
テスト
このロールには、Molecule、libvirt(vagrant-libvirt)、およびQEMU/KVMを使用して作成された小さなテストセットアップがあります。テストの設定方法については、私のブログ記事「Molecule、libvirt(vagrant-libvirt)、およびQEMU/KVMを使ったAnsibleロールのテスト」を参照してください。テスト設定はこちらです。
その後、以下のコマンドでMoleculeを実行できます:
molecule converge
これにより、異なるサポートされているLinuxオペレーティングシステムを持ついくつかの仮想マシン(VM)が設定され、harden_linux
ロールが適用されます。小さな検証ステップも含まれています:
molecule verify
クリーンアップを実行するには、次のコマンドを使用します:
molecule destroy
ライセンス
GNU一般公衆ライセンス バージョン3
著者情報
Ansible role for hardening Linux
ansible-galaxy install githubixx.harden_linux