Red Hat Training

A Red Hat training course is available for RHEL 8

10.7. 例: nftables スクリプトを使用した LAN および DMZ の保護

RHEL ルーターで nftables フレームワークを使用して、内部 LAN 内のネットワーククライアントと DMZ の Web サーバーを、インターネットやその他のネットワークからの不正アクセスから保護するファイアウォールスクリプトを作成およびインストールします。

重要

この例はデモ目的専用で、特定の要件があるシナリオを説明しています。

ファイアウォールスクリプトは、ネットワークインフラストラクチャーとセキュリティー要件に大きく依存します。この例を使用して、独自の環境用のスクリプトを作成する際に nftables ファイアウォールの概念を理解してください。

10.7.1. ネットワークの状態

この例のネットワークは、以下の条件下にあります。

  • ルーターは以下のネットワークに接続されています。

    • インターフェイス enp1s0を介したインターネット
    • インターフェイス enp7s0を介した内部 LAN
    • enp8s0までの DMZ
  • ルーターのインターネットインターフェイスには、静的 IPv4 アドレス (203.0.113.1) と IPv6 アドレス (2001:db8:a::1) の両方が割り当てられています。
  • 内部 LAN のクライアントは 10.0.0.0/24 の範囲のプライベート IPv4 アドレスのみを使用します。その結果、LAN からインターネットへのトラフィックには、送信元ネットワークアドレス変換 (SNAT) が必要です。
  • 内部 LAN の管理者用 PC は、IP アドレス 10.0.0.100 および 10.0.0.200 を使用します。
  • DMZ は、198.51.100.0/24 および 2001:db8:b::/56 の範囲のパブリック IP アドレスを使用します。
  • DMZ の Web サーバーは、IP アドレス 198.51.100.5 および 2001:db8:b::5 を使用します。
  • ルーターは、LAN および DMZ 内のホストのキャッシング DNS サーバーとして機能します。

10.7.2. ファイアウォールスクリプトのセキュリティー要件

以下は、サンプルネットワークにおける nftables ファイアウォールの要件です。

  • ルーターは以下を実行できる必要があります。

    • DNS クエリーを再帰的に解決します。
    • ループバックインターフェイスですべての接続を実行します。
  • 内部 LAN のクライアントは以下を実行できる必要があります。

    • ルーターで実行しているキャッシング DNS サーバーをクエリーします。
    • DMZ の HTTPS サーバーにアクセスします。
    • インターネット上の任意の HTTPS サーバーにアクセスします。
  • 管理者用の PC は、SSH を使用してルーターと DMZ 内のすべてのサーバーにアクセスできる必要があります。
  • DMZ の Web サーバーは以下を実行できる必要があります。

    • ルーターで実行しているキャッシング DNS サーバーをクエリーします。
    • インターネット上の HTTPS サーバーにアクセスして更新をダウンロードします。
  • インターネット上のホストは以下を実行できる必要があります。

    • DMZ の HTTPS サーバーにアクセスします。
  • さらに、以下のセキュリティー要件が存在します。

    • 明示的に許可されていない接続の試行はドロップする必要があります。
    • ドロップされたパケットはログに記録する必要があります。

10.7.3. ドロップされたパケットをファイルにロギングするための設定

デフォルトでは、systemd は、ドロップされたパケットなどのカーネルメッセージをジャーナルに記録します。さらに、このようなエントリーを別のファイルに記録するように rsyslog サービスを設定することもできます。ログファイルが無限に大きくならないようにするために、ローテーションポリシーを設定します。

前提条件

  • rsyslog パッケージがインストールされている。
  • rsyslog サービスが実行されている。

手順

  1. 以下の内容で /etc/rsyslog.d/nftables.conf ファイルを作成します。

    :msg, startswith, "nft drop" -/var/log/nftables.log
    & stop

    この設定を使用すると、rsyslog サービスはドロップされたパケットを /var/log/messages ではなく /var/log/nftables.log ファイルに記録します。

  2. rsyslog サービスを再起動します。

    # systemctl restart rsyslog
  3. サイズが 10 MB を超える場合は、以下の内容で /etc/logrotate.d/nftables ファイルを作成し、/var/log/nftables.log をローテーションします。

    /var/log/nftables.log {
      size +10M
      maxage 30
      sharedscripts
      postrotate
        /usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
      endscript
    }

    maxage 30 設定は、次のローテーション操作中に logrotate が 30 日経過したローテーション済みログを削除することを定義します。

関連情報

  • rsyslog.conf(5) の man ページ
  • logrotate(8) の man ページ

10.7.4. nftables スクリプトの作成とアクティブ化

この例は、RHEL ルーターで実行され、DMZ の内部 LAN および Web サーバーのクライアントを保護する nftables ファイアウォールスクリプトです。この例で使用されているネットワークとファイアウォールの要件について、詳しくはファイアウォールスクリプトの ネットワークの状態 および ファイアウォールスクリプトのセキュリティー要件 を参照してください。

警告

この nftables ファイアウォールスクリプトは、デモ専用です。お使いの環境やセキュリティー要件に適応させて使用してください。

前提条件

手順

  1. 以下の内容で /etc/nftables/firewall.nft スクリプトを作成します。

    # Remove all rules
    flush ruleset
    
    
    # Table for both IPv4 and IPv6 rules
    table inet nftables_svc {
    
      # Define variables for the interface name
      define INET_DEV = enp1s0
      define LAN_DEV  = enp7s0
      define DMZ_DEV  = enp8s0
    
    
      # Set with the IPv4 addresses of admin PCs
      set admin_pc_ipv4 {
        type ipv4_addr
        elements = { 10.0.0.100, 10.0.0.200 }
      }
    
    
      # Chain for incoming trafic. Default policy: drop
      chain INPUT {
        type filter hook input priority filter
        policy drop
    
        # Accept packets in established and related state, drop invalid packets
        ct state vmap { established:accept, related:accept, invalid:drop }
    
        # Accept incoming traffic on loopback interface
        iifname lo accept
    
        # Allow request from LAN and DMZ to local DNS server
        iifname { $LAN_DEV, $DMZ_DEV } meta l4proto { tcp, udp } th dport 53 accept
    
        # Allow admins PCs to access the router using SSH
        iifname $LAN_DEV ip saddr @admin_pc_ipv4 tcp dport 22 accept
    
        # Last action: Log blocked packets
        # (packets that were not accepted in previous rules in this chain)
        log prefix "nft drop IN : "
      }
    
    
      # Chain for outgoing traffic. Default policy: drop
      chain OUTPUT {
        type filter hook output priority filter
        policy drop
    
        # Accept packets in established and related state, drop invalid packets
        ct state vmap { established:accept, related:accept, invalid:drop }
    
        # Accept outgoing traffic on loopback interface
        oifname lo accept
    
        # Allow local DNS server to recursively resolve queries
        oifname $INET_DEV meta l4proto { tcp, udp } th dport 53 accept
    
        # Last action: Log blocked packets
        log prefix "nft drop OUT: "
      }
    
    
      # Chain for forwarding traffic. Default policy: drop
      chain FORWARD {
        type filter hook forward priority filter
        policy drop
    
        # Accept packets in established and related state, drop invalid packets
        ct state vmap { established:accept, related:accept, invalid:drop }
    
        # IPv4 access from LAN and internet to the HTTPS server in the DMZ
        iifname { $LAN_DEV, $INET_DEV } oifname $DMZ_DEV ip daddr 198.51.100.5 tcp dport 443 accept
    
        # IPv6 access from internet to the HTTPS server in the DMZ
        iifname $INET_DEV oifname $DMZ_DEV ip6 daddr 2001:db8:b::5 tcp dport 443 accept
    
        # Access from LAN and DMZ to HTTPS servers on the internet
        iifname { $LAN_DEV, $DMZ_DEV } oifname $INET_DEV tcp dport 443 accept
    
        # Last action: Log blocked packets
        log prefix "nft drop FWD: "
      }
    
    
      # Postrouting chain to handle SNAT
      chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
    
        # SNAT for IPv4 traffic from LAN to internet
        iifname $LAN_DEV oifname $INET_DEV snat ip to 203.0.113.1
      }
    }
  2. /etc/nftables/firewall.nft スクリプトを /etc/sysconfig/nftables.conf ファイルに追加します。

    include "/etc/nftables/firewall.nft"
  3. IPv4 転送を有効にします。

    # echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf
    # sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf
  4. nftables サービスを有効にして起動します。

    # systemctl enable --now nftables

検証

  1. オプション: nftables ルールセットを確認します。

    # nft list ruleset
    ...
  2. ファイアウォールが阻止するアクセスの実行を試みます。たとえば、DMZ から SSH を使用してルーターにアクセスします。

    # ssh router.example.com
    ssh: connect to host router.example.com port 22: Network is unreachable
  3. ロギング設定に応じて、以下を検索します。

    • ブロックされたパケットの systemd ジャーナル:

      # journalctl -k -g "nft drop"
      Oct 14 17:27:18 router kernel: nft drop IN : IN=enp8s0 OUT= MAC=... SRC=198.51.100.5 DST=198.51.100.1 ... PROTO=TCP SPT=40464 DPT=22 ... SYN ...
    • ブロックされたパケットの /var/log/nftables.log ファイル:

      Oct 14 17:27:18 router kernel: nft drop IN : IN=enp8s0 OUT= MAC=... SRC=198.51.100.5 DST=198.51.100.1 ... PROTO=TCP SPT=40464 DPT=22 ... SYN ...