Linuxでポートノッキングを使用する方法(および使用すべきでない理由)

  • ポートノッキングは、ファイアウォールのポートを閉じて、特定の接続試行のシーケンスが行われた場合にのみアクセスを許可することで、サーバーを保護する方法です。
  • シークレットノックが漏洩した場合には簡単に突破されるため、ポートノッキングを唯一のセキュリティ手段として依存すべきではありません。

ポートノッキングとは、ファイアウォールのポートを閉じてサーバーを保護する方法です。使用するポートは既知のポートでも閉じてしまいます。これらのポートは、接続要求がシークレットノックを提供する場合にのみ、必要に応じて開きます。

ポートノッキングは「シークレットノック」

1920年代、禁酒法が施行されていたとき、スピークイージーに入りたい人は、シークレットノックを知っていて、それを正しく叩いて中に入らなければなりませんでした。

ポートノッキングは、その現代版です。コンピューター上のサービスに誰かにアクセスさせたいが、ファイアウォールをインターネットに開きたくない場合は、ポートノッキングを使用できます。これにより、着信接続を許可するファイアウォールのポートを閉じて、接続試行のあらかじめ決められたパターンが行われたときに自動的に開くことができます。接続試行のシーケンスはシークレットノックとして機能します。別のシークレットノックでポートを閉じます。

ポートノッキングは目新しいものですが、それがセキュリティバイオブスキュリティーの一例であり、その概念には根本的な欠陥があることを理解することが重要です。システムにアクセスする方法の秘密は、特定のグループの人しか知らないため安全です。しかし、その秘密が漏洩した場合(それが明らかにされた、観察された、推測された、または解決された場合)、セキュリティは無効になります。SSHサーバーの鍵ベースのログインを要求するなど、他のより強力な方法でサーバーを保護することをお勧めします。

サイバーセキュリティに対する最も堅牢なアプローチは多層的であるため、ポートノッキングはそのレイヤーの1つであるべきです。レイヤーが多いほど良いですよね?ただし、ポートノッキングは、適切に強化された安全なシステムにはあまり(またはまったく)追加されない可能性があります。

サイバーセキュリティは広大で複雑なトピックですが、ポートノッキングを唯一の防御手段として使用すべきではありません。

knockdのインストール

ポートノッキングを実証するために、SSHポートであるポート22を制御するために使用します。knockdというツールを使用します。Ubuntuまたはその他のDebianベースのディストリビューションを使用している場合は、apt-getを使用してこのパッケージをシステムにインストールします。他のLinuxディストリビューションでは、代わりにLinuxディストリビューションのパッケージ管理ツールを使用します。

次のように入力します:

sudo apt-get install knockd

おそらくシステムにiptablesファイアウォールがすでにインストールされていますが、iptables-persistentパッケージをインストールする必要がある場合があります。これは、保存されたiptableルールの自動ロードを処理します。

次のように入力してインストールします:

sudo apt-get install iptables-persistent

IPV4構成画面が表示されたら、スペースバーを押して「はい」オプションを受け入れます。

IPv6構成画面でスペースバーをもう一度押して「はい」オプションを受け入れ、先に進みます。

次のコマンドはiptablesに、確立された継続中の接続を継続することを許可します。次に、別のコマンドを発行してSSHポートを閉じます。

このコマンドを発行したときに、誰かがSSHで接続されている場合、その接続が切断されないようにします:

sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

このコマンドは、ファイアウォールに次のルールを追加します:

  • -A:ファイアウォールルールテーブルにルールを追加します。つまり、一番下に追加します。
  • INPUT:これは着信接続に関するルールです。
  • -m conntrack:ファイアウォールルールは、ルール内の基準と一致するネットワークトラフィック(パケット)に対して機能します。-mパラメータによりiptablesは追加のパケットマッチングモジュールを使用します。この場合、conntrackと呼ばれるモジュールはカーネルのネットワーク接続追跡機能と連携します。
  • --cstate ESTABLISHED,RELATED:これは、ルールが適用される接続の種類、つまりESTABLISHED接続とRELATED接続を指定します。確立された接続とは、すでに進行中の接続です。関連接続とは、確立された接続からのアクションによって行われた接続です。接続している人がファイルをダウンロードしたい場合があるかもしれません。それはホストによって開始された新しい接続で行われる可能性があります。
  • -j ACCEPT:トラフィックがルールと一致した場合、ファイアウォールのACCEPTターゲットにジャンプします。言い換えると、トラフィックは受け入れられ、ファイアウォールを通過することが許可されます。

これで、ポートを閉じるコマンドを発行できます。

sudo iptables -A INPUT -p tcp --dport 22 -j REJECT

このコマンドは、ファイアウォールに次のルールを追加します:

  • -A:ファイアウォールルールテーブルにルールを追加します。つまり、一番下に追加します。
  • INPUT:このルールは着信接続に関するものです。
  • -p tcp:このルールは、Transmission Control Protocolを使用するトラフィックに適用されます。
  • --dport 22:このルールは、特にポート22(SSHポート)をターゲットにしたTCPトラフィックに適用されます。
  • -j REJECT:トラフィックがルールと一致した場合、ファイアウォールのREJECTターゲットにジャンプします。したがって、トラフィックが拒否された場合、ファイアウォールを通過することは許可されません。

netfilter-persistentデーモンを起動する必要があります。これは、次のコマンドで実行できます:

sudo systemctl start netfilter-persistent

netfilter-persistentを保存してリロードサイクルを実行して、iptableルールをロードして制御できるようにします。

次のコマンドを入力します:

sudo netfilter-persistent save

sudo netfilter-persistent reload

これで、ユーティリティがインストールされ、SSHポートが閉じられました(誰の接続も終了せずに)。次に、シークレットノックを構成します。

knockdの構成

knockdを構成するには、2つのファイルを編集します。1つ目は、次のknockd構成ファイルです:

sudo gedit /etc/knockd.conf

geditエディタがknockd構成ファイルを読み込んで開きます。

このファイルを編集して、ニーズに合わせていきます。興味のあるセクションは「openSSH」と「closeSSH」です。各セクションには、次の4つのエントリがあります:

  • sequence:ポート22を開いたり閉じたりするために、誰かがアクセスする必要があるポートのシーケンス。デフォルトのポートは、開く場合は7000、8000、9000で、閉じる場合は9000、8000、7000です。これらを変更したり、リストにポートを追加したりすることができます。ここでは、デフォルトのままにします。
  • seq_timeout:誰かがポートにアクセスして開いたり閉じたりする必要がある時間枠。
  • command:開くまたは閉じるアクションがトリガーされたときにiptablesファイアウォールに送信されるコマンド。これらのコマンドは、ファイアウォールにルールを追加(ポートを開く)するか、削除(ポートを閉じる)します。
  • tcpflags:シークレットシーケンスで各ポートが受信する必要があるパケットの種類。SYN(同期)パケットは、3ウェイハンドシェイクと呼ばれるTCP接続リクエストの最初のものです。

「openSSH」セクションは、「TCP接続リクエストは、ポート7000、8000、9000に(その順序で、5秒以内に)行われなければなりません。そうしないと、ポート22を開くコマンドがファイアウォールに送信されません」と解釈できます。

「closeSSH」セクションは、「TCP接続リクエストは、ポート9000、8000、7000に(その順序で、5秒以内に)行われなければなりません。そうしないと、ポート22を閉じるコマンドがファイアウォールに送信されません」と解釈できます。

ファイアウォールのルール

openSSHとcloseSSHセクションの「command」エントリは、1つのパラメータを除いて同じままです。以下にその構成を示します:

  • -A:ルールをファイアウォールルールリストの末尾に追加します(openSSHコマンドの場合)。
  • -D:ファイアウォールルールリストからコマンドを削除します(closeSSHコマンドの場合)。
  • INPUT:このルールは、着信ネットワークトラフィックに関係しています。
  • -s %IP%:接続を要求するデバイスのIPアドレス。
  • -p:ネットワークプロトコル。ここではTCPです。
  • --dport:宛先ポート。この例ではポート22です。
  • -j ACCEPT:ファイアウォールのacceptターゲットにジャンプします。言い換えると、パケットをそれ以上のアクションを行わずにルールをすべて通過させます。

knockd構成ファイルの編集

ファイルに加える編集は、以下で赤で強調表示されています:

「seq_timeout」を15秒に延長します。これは寛大ですが、誰かが手動で接続リクエストを送信する場合、これだけの時間がかかる場合があります。

「openSSH」セクションでは、コマンドの-A(追加)オプションを-I(挿入)に変更します。このコマンドは、新しいファイアウォールルールをファイアウォールルールリストの先頭に追加します。-Aオプションを残しておくと、ファイアウォールルールリストに追加され、末尾に配置されます。

着信トラフィックは、リスト内の各ファイアウォールルールに対して上から下へと照合されます。ポート22を閉じるルールがすでにあります。したがって、着信トラフィックがトラフィックを許可するルールを見る前にそのルールに対して照合されると、接続は拒否されます。この新しいルールを最初に表示すると、接続が許可されます。

closeコマンドは、openSSHによって追加されたルールをファイアウォールルールから削除します。SSHトラフィックは、再び既存の「ポート22は閉じている」ルールによって処理されます。

これらの編集を行ったら、構成ファイルを保存します。

knockd制御ファイルの編集

knockd制御ファイルは、全体として単純です。ただし、その前に編集する必要があるのは、ネットワーク接続の内部名です。見つけるには、次のコマンドを入力します:

ip addr

この記事を調査するためにこのマシンが使用する接続はenp0s3と呼ばれます。接続の名前をメモしておきます。

次のコマンドはknockd制御ファイルを編集します:

sudo gedit /etc/default/knockd

geditknockdファイルがここにあります。

必要な編集は赤で強調表示されています:

「START_KNOCKD=」エントリを0から1に変更しました。

また、「KNOCKD_OPTS=」エントリの先頭からハッシュ#を削除し、「eth1」をネットワーク接続の名前enp0s3に置き換えました。もちろん、ネットワーク接続がeth1の場合は、変更しません。

証明はプディングにある

これが機能するかどうかを確認しましょう。このコマンドでknockdデーモンを起動します:

sudo systemctrl start knockd

次に、別のマシンに移動して接続してみます。そのコンピューターにもknockdツールをインストールしましたが、ポートノッキングを設定したいからではなく、knockdパッケージにknockという別のツールが提供されているからです。このマシンを使用してシークレットシーケンスを起動し、ノックを実行します。

次のコマンドを使用して、ポートノッキングホストコンピューターのポートに接続リクエストのシークレットシーケンスをIPアドレス192.168.4.24で送信します:

knock 192.168.4.24 7000 8000 9000 -d 500

これにより、knockはIPアドレス192.168.4.24のコンピューターをターゲットにして、ポート7000、8000、9000に接続リクエストを送信します。その間には-d(遅延)が500ミリ秒あります。

次に、「dave」というユーザーが192.168.4.24にSSHリクエストを行います:

ssh [email protected]

彼の接続は受け入れられ、パスワードを入力するとリモートセッションが開始されます。コマンドプロンプトはdave@nostromoからdave@howtogeekに変更されます。リモートコンピューターからログアウトするには、次のように入力します:

exit

コマンドプロンプトはローカルコンピューターに戻ります。彼はknockをもう一度使用し、今度はリモートコンピューターのSSHポートを閉じるために逆順でポートをターゲットにします。

knock 192.168.4.24 9000 8000 7000 -d 500

確かに、これは特に有益なリモートセッションではありませんでしたが、ポートノッキングによるポートの開閉を実証し、1つのスクリーンショットに収まっています。

では、これは反対側からどう見えたのでしょうか?ポートノッキングホストのシステム管理者は、次のコマンドを使用してシステムログに届いた新しいエントリを表示します:

tail -f /var/log/syslog

  • openSSHエントリが3つあります。これらは、リモートノックユーティリティによって各ポートがターゲットにされるときに発生します。
  • トリガシーケンスの3つのステージがすべて満たされると、「OPEN SESAME」というエントリがログに記録されます
  • ルールをiptablesルールリストに挿入するコマンドが送信されます。正しいシークレットノック(192.168.4.23)を与えたPCの特定のIPアドレスから、ポート22でSSH経由のアクセスを許可します。
  • ユーザー「dave」は数秒間だけ接続し、切断します。
  • closeSSHエントリが3つあります。これらは、リモートノックユーティリティによって各ポートがターゲットにされるときに発生します。ポートノッキングホストにポート22を閉じるように指示します。
  • 3つのステージがすべてトリガーされると、「OPEN SESAME」メッセージが再び表示されます。ルールを削除するコマンドがファイアウォールに送信されます。(ポートを閉じるときに「CLOSE SESAME」にならないのはなぜですか?それはわかりません。)

ポート22に関するiptablesルールリストの唯一のルールは、ポートを閉じるために最初にタイプしたルールです。したがって、ポート22は再び閉じられました。

ノックは頭に

それがポートノッキングの奇術です。それを単なる気晴らしとして扱い、現実世界では行わないようにしてください。または、どうしても行う必要がある場合は、セキュリティの唯一の方法として頼らないでください。