ノードのセキュリティ保護

このガイドの目的は、悪意のある攻撃者からノードを保護するための手順を説明することです。 自宅でローカルサーバーを運用している場合でも、クラウド上でVPSサーバーや仮想マシンを運用している場合でも、ここで紹介するヒントは、外部からの攻撃に対してノードを強化し、その寿命の間保護するのに役立ちます。

このセクションでは、必須のアクション(必ず実行する必要があるもの)と、あると良いアクション(役立ちますが必須ではないもの)の両方を説明します。

注記

このガイドは、ノードマシンを強化するためにできることの入門として意図されています。 コマンドラインターミナルに慣れており、ノードをさらに保護したい場合は、人気の高いimthenachoman/How-To-Secure-A-Linux-Serverガイドをご覧ください。

このガイドの前提条件

このガイドは、ノードがUbuntu 20.04 LTSで動作していることを前提としています。 概念は他のシステムにも適用できますが、サンプルコマンドは適用できない場合があります。

このガイドのすべてのコマンドと同様に、sshを使用してノードのコマンドターミナルにリモートで接続していることを前提としています。 sshの使い方を復習する必要がある場合は、まずSecure Shellの紹介ガイドをご覧ください。

必須: クライアントマシンのセキュリティを確保する

注記

Smartnodeをローカルで使用している(キーボードとモニターを直接接続して物理的にログインしている)場合、このセクションは関係ありません - スキップできます

ほとんどのSmartnodeオペレーターは、sshを使用して別のコンピューターからターミナルに接続することで、ノードとリモートでやり取りします。

  • 接続のマシン(この場合、ノードマシン)はサーバーと呼ばれます。
  • 接続のマシン(ラップトップ、デスクトップ、さらにはスマートフォンなど)はクライアントと呼ばれます。

Smartnodeを保護するために最も重要なことの1つは、クライアントマシンのセキュリティを確保することです。 クライアントマシンが侵害され、それを使用してノードにログインした場合、ノードに適用するセキュリティ設定のほとんどをバイパスできます。

たとえば、ラップトップをSSHクライアントとして使用し、キーロガーがインストールされている場合、SSH経由で接続しているときにノードで入力した秘密のもの(パスワードやリカバリーニーモニックなど)は盗まれます。

クライアントマシンのセキュリティを確保するための決定的なガイドはありませんが、それがセキュリティの要因であることを認識することは良い第一歩です。 クライアントマシンができる限り安全であることを確認してください。

いくつかのヒントを以下に示します。

  • クライアントマシンを危険な活動(信頼できないウェブサイトへのアクセスや不要なプログラムのインストールなど)に使用しない
  • クライアントマシンを最新のセキュリティパッチで更新し続ける
  • 可能であれば、オペレーティングシステム用のマルウェアおよびアンチウイルス保護プログラムを使用する

最大限のセキュリティを確保するために、SSHクライアントとして専用マシンを使用することをお勧めしますが、これは実用的ではない場合があります。

必須: SSHアクセスのセキュリティを確保する

注記

Smartnodeをローカルで使用している(キーボードとモニターを直接接続して物理的にログインしている)場合、このセクションは関係ありません - スキップできます

自宅でSmartnodeを運用している場合でも、リモートデータセンターでVPSを使用している場合でも、SSH経由でアクセスするか、使用していなくてもSSHが有効になっている可能性があります。

SSH接続は安全な暗号化に基づいていますが、すべての安全なシステムと同様に、本当のセキュリティは正しく使用することから生まれます。 SSH設定で行うべき主なことは2つあります。

  1. ユーザー名とパスワードの代わりにSSHキーを使用してリモートログインする
  2. パスワードベースの認証を完全に無効にし、SSHキーのみをリモートログインオプションにする

おそらくご存知のとおり、SSH経由でノードにログインするデフォルトの方法は、ユーザー名とパスワードを使用することです。 これの欠点は、パスワードが通常かなり「短く」、ブルートフォース攻撃に対して脆弱であることです。

幸いなことに、SSH経由でログインする別の方法があります。SSHキーペアです。

SSHキーペアはブロックチェーンウォレットと同様に機能します。公開部分(ウォレットアドレスなど)と秘密部分(ウォレットアドレスの秘密鍵)が付属しています。

  • 公開部分をノードに提供します。これにより、ノードはあなたが接続を許可されていることを認識し、実際にあなたが接続しようとしていることを認識します。
  • 秘密部分はクライアントマシンに保管します。これにより、あなた(そしてあなただけ)がノードに接続できます。
    • 秘密部分をパスワードで保護できます(そしてすべきです!)。これにより、キーを盗んだ人がそれを使用できなくなります。
  • コンピューターの観点から見ると、秘密鍵はパスワードよりも指数関数的に解読が困難です。これにより、ノードに対するブルートフォース攻撃のリスクが軽減されます。
ヒント

SSHキーペアを作成する前に詳しく知りたい場合は、以下のリンクをご覧ください。

SSHキーペアの作成

クライアントマシンで新しいSSHキーペアを作成することから始めましょう。 キーにはさまざまな種類がありますが、優れたセキュリティを提供するed25519と呼ばれるキータイプを使用します。

クライアントマシンで次のコマンドを実行します(つまり、ノードマシンにSSH接続している間にこれを実行しないでください - 接続している場合は、最初にSSHから抜けてください)。

ssh-keygen -t ed25519 -C "your_email@example.com"

次のように表示されます。

Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/username/.ssh/id_ed25519):

これは、秘密鍵ファイルを保存する場所を尋ねています。 SSHは提供されたデフォルトと互換性があり、それを選択すると自動的に使用されます。 ただし、必要に応じて別のものに変更することもできます。

注記

パス/home/username/.ssh/id_ed25519は単なる例で、ユーザー名がusernameであると仮定しています。 おそらく別のユーザー名を持っています。 このガイドで上記のようなパスが表示された場合は、システムが実際のユーザー名で実際に出力したパスに置き換えてください。

デフォルト設定で問題ない場合は、単にEnterを押してください。

それ以外の場合は、キーの希望の場所を入力してください。 絶対パスである必要があります(例:Linuxでは/home/username/.ssh/rocketpool_key、macOSでは/Users/username/.ssh/rocketpool_key)。 完了したらEnterを押してください。

Enterを押すと、次のように表示されます。

Enter passphrase (empty for no passphrase):

これが秘密鍵自体のパスワードになります。 ノードに接続するためにキーを使用するたびに、最初にこのパスワードを入力する必要があります。

警告

これを空白のままにしないでください - そうしないと、SSHキーファイルを持っている人なら誰でも使用できるようになります! あなた(そしてあなただけ)が知っている良いパスワードを選択してください。

また、パスワードを忘れないでください - このパスワードを失った場合、回復する方法はありません。

パスワードの入力が完了したら、Enterを押してください。 確認のために再入力するように求められます。

その後、次のような出力が表示されます。

Your identification has been saved in /home/username/.ssh/id_ed25519
Your public key has been saved in /home/username/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:CASbPZETiQ83lLhpUO2aoT05TxMVLwqiWtdsRtoPt4s your_email@example.com
The key's randomart image is:
+--[ED25519 256]--+
| .o*==..         |
|. +=O...         |
|..+B++o .        |
|..=.+X o         |
|.+.=+.O S        |
|o.B.oo + .       |
|.  = .  o        |
|    .  . .       |
|      E .        |
+----[SHA256]-----+

最初の行は秘密鍵の場所を示しており、デフォルトではid_ed25519と呼ばれます(ファイル拡張子がないことに注意してください)。 この秘密鍵ファイルがデフォルトの場所にある場合、Ubuntuはsshを使用するときに自動的にこのキーを読み込みます。

2行目は公開鍵の場所を示しており、デフォルトではid_ed25519.pubと呼ばれます。 次のステップで公開鍵が必要になります。

注記

Ubuntuはこの新しいキーを自動的に読み込むはずです。 ただし、一部のシステム(macOSマシンなど)は自動的に読み込まれません - クライアントマシンで次のコマンドを使用してこれを行うように指示する必要があります。

ssh-add $HOME/.ssh/id_ed25519

これは、前のステップで生成した秘密鍵のパスであり、公開鍵ではないことに注意してください。 前のステップでシステムが出力したパスに置き換えてください。

ssh-agentが実行されていないというエラーが表示された場合は、クライアントマシンで次のコマンドを実行して起動します。

eval $(ssh-agent)

ターミナルを開くたびにこれらの2つのコマンドを入力したくない場合は、~/.bashrcファイルにaliasを追加して、キーを追加するためのショートカットを作成できます。

テキストエディタでファイルを開きます。

nano ~/.bashrc

最後に次の行を追加します(秘密鍵にデフォルトのパスを使用したと仮定して - 必要に応じて更新してください)。

alias loadkey='ssh-add $HOME/.ssh/id_ed25519'

Ctrl+OEnterで保存して終了し、次にCtrl+Xで終了します。 次に、ターミナルを閉じて開き、変更を有効にします。

これで、クライアントマシンloadkeyと入力してキーを読み込むことができます。

ノードへの公開鍵の追加

SSHキーペアを取得したら、公開鍵をノードに追加できます。 これにより、生成した秘密鍵を使用してssh経由で接続できるようになり、ユーザー名とパスワードの代わりになります。

これを行うには2つの方法があります - 一方が機能しない場合は、もう一方の方法を試してください。

ssh-copy-idを使用する
手動でキーを追加する

注記: クライアントマシンがWindowsを実行している場合、ssh-copy-idはまだ利用できません。 「手動でキーを追加する」タブの手順に従ってください。

クライアントマシンで次のコマンドを実行します。

ssh-copy-id -i $HOME/.ssh/id_ed25519.pub username@node.ip.address

たとえば、ノード上のユーザー名がstakerで、ノードのIPアドレスが192.168.1.10の場合、次のコマンドを実行します。

ssh-copy-id -i $HOME/.ssh/id_ed25519.pub staker@192.168.1.10

次のようなメッセージが表示されます。

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/username/.ssh/id_ed25519.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys

これは、キーが既にそこにないことを確認するために、最初にキーでログインしようとしていることを示しています。 ログインに失敗すると、新しい公開鍵をノードマシンに追加しても問題ないことがわかります。

次に、ノードマシン上のユーザーのパスワードを要求されます。 (これはSSHキーのパスワードではありません

ユーザーのパスワードを入力すると、次の出力が表示されます。

Number of key(s) added: 1

Now try logging into the machine with:   "ssh 'username@node.ip.address'"
and check to make sure that only the key(s) you wanted were added.

それは成功したことを意味します!

これで、通常どおりsshでノードにログインできるようになりますが、ユーザーアカウントのパスワードを入力する必要はなくなりました。

代わりに、SSH秘密鍵のパスワードを入力する必要があります。 システム設定によっては、再起動ごとに1回だけ入力する必要がある場合もあれば、ノードに接続するためにキーを使用するたびに入力する必要がある場合もあります。

パスワードでのログインを無効にする

SSHキーペアが設定されていても、ノードは他のマシンがユーザー名とパスワード方式を使用してログインしようとすることを許可します。 これはSSHキーを使用する目的全体を無効にするため、次のステップはそれらを無効にすることです。

注記

これからSSHサーバーの構成を変更します。 既存のSSHセッションはすべて保持されます。 ただし、間違えた場合、新しいSSHセッションを作成できなくなり、事実上マシンからロックアウトされる可能性があります。

これを防ぐために、次のステップでは2つのSSHセッションを作成することを強くお勧めします - 1つは編集とテスト用、もう1つはバックアップとして、破壊的な変更を元に戻すことができます。

通常どおりsshを使用してマシンにログインすることから始めます。

ssh user@your.node.ip.address

注意として、念のため、2つの別々のターミナルでこれを2回実行する必要があります。 バックアップセッションは今のところ無視できます - 必要なときに通知します。 次のコマンドは最初のセッションでのみ実行してください。

SSHサーバーの構成ファイルを開きます。

sudo nano /etc/ssh/sshd_config

sudoで始まるすべてのコマンドと同様に、これはユーザーアカウントのパスワードを要求します。 これは大きなファイルなので、キーボードの矢印キーまたはPage Up / Page Downを使用してナビゲートする必要があります。

次の変更を加えます。

  1. コメントされている場合は#AuthorizedKeysFileのコメントを解除します(前の#を削除します)
  2. KbdInteractiveAuthentication yesKbdInteractiveAuthentication noに変更し、コメントを解除します(前の#を削除します) - 古いバージョンのSSHでは、このオプションはKbdInteractiveAuthenticationではなくChallengeResponseAuthenticationと呼ばれることに注意してください
  3. PasswordAuthentication yesPasswordAuthentication noに変更し、コメントを解除します(前の#を削除します)
  4. PermitRootLogin yesPermitRootLogin prohibit-passwordに変更します(既にそれに設定されていて前に#がない場合を除く)

完了したら、Ctrl+OEnterで保存し、Ctrl+Xで終了します。

最後に、sudo sshd -T | grep -i passwordauthenticationを実行し、passwordauthentication noが出力されることを確認します。 出力されない場合は、sudo nano /etc/ssh/sshd_config.d/50-cloud-init.confを実行し、そのファイルでもPasswordAuthentication yesPasswordAuthentication noに設定する必要がある場合があります。 前と同じように保存して終了し、Ctrl+OEnter、次にCtrl+Xで終了します。

次に、SSHサーバーを再起動して新しい設定を取得します。

sudo systemctl restart ssh.service

この後、ユーザー名とパスワードを介したSSHログインが無効になります。

注記

この時点で、SSHセッションを終了し、再度SSHで接続してみる必要があります。 正常に接続できる場合、SSH構成はまだ有効です!

接続できない場合は、構成に何か問題が発生しています。 このセクションの最初に作成したバックアップSSHセッションを使用して、/etc/ssh/sshd_configファイルを変更します。

間違いを見つけるか、変更を元に戻してから、sudo systemctl restart sshdを使用してSSHサーバーを再起動してください。

再起動されたら、「他の」ターミナルでSSHで再度接続してみてください。 再び正常に接続できるまでこれを続けてください。

(オプション)二要素認証を有効にする

二要素認証には、通常、パスワードまたはSSHキーに加えて、プライマリデバイスとは別のデバイスで2番目のセキュリティ対策が必要です。

たとえば、暗号通貨取引所などのウェブサイトにパスワードとGoogle Authenticatorコード(またはSMSコード)の両方を使用してログインすることに慣れているかもしれません。 この2ステップのプロセスは、二要素認証の例です。

SSHはGoogle Authenticatorコードを要求するように構成することもできます。これは、何らかの方法でSSHキーとそのパスフレーズを侵害した攻撃者が、認証アプリがインストールされたデバイス(おそらくあなたの電話)をまだ必要とすることを意味します。 これにより、システムにセキュリティの層が追加されます。

警告

何かを誤って構成した場合に備えて、ノードへのSSH接続を備えた2番目のターミナルを開くことを強くお勧めします。 これにより、ロックアウトされた場合でもバックアップが接続されているため、間違いを簡単に元に戻すことができます。

ロックアウトされた場合、ログインして誤った構成を修復するには、ローカルモニターとキーボードを介してノードに物理的にアクセスする必要があります。

まず、まだインストールしていない場合は、電話にGoogle Authenticator(または互換性のある同等のもの)をインストールします。 Androidユーザーの場合、パスワードロックと便利なバックアップをサポートするオープンソースの代替としてandOTPを検討してください。

次に、次のコマンドでノードにGoogle Authenticatorモジュールをインストールします。

sudo apt install -y libpam-google-authenticator

次に、このモジュールを使用するようにPAM(プラグイン可能な認証モジュール)に指示します。 まず、構成ファイルを開きます。

sudo nano /etc/pam.d/sshd

@include common-authを見つけて(先頭にあるはずです)、前に#を追加してコメントアウトします。次のようになります。

# Standard Un*x authentication.
#@include common-auth

次に、これらの行をファイルの先頭に追加します。

# Enable Google Authenticator
auth required pam_google_authenticator.so

次に、Ctrl+OEnterCtrl+Xでファイルを保存して終了します。

PAMがGoogle Authenticatorを使用することを認識したので、次のステップはsshdPAMを使用するように指示することです。 sshd構成ファイルを開きます。

sudo nano /etc/ssh/sshd_config

次に、KbdInteractiveAuthentication noの行をKbdInteractiveAuthentication yesに変更して、次のようにします。

# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
KbdInteractiveAuthentication yes

(古いバージョンのSSHでは、このオプションはKbdInteractiveAuthenticationではなくChallengeResponseAuthenticationと呼ばれます。)

ファイルの最後に次の行を追加します。これは、SSHキーとGoogle Authenticatorコードの両方が必要であることをsshdに示します。

AuthenticationMethods publickey,keyboard-interactive:pam

次に、Ctrl+OEnterCtrl+Xでファイルを保存して終了します。

sshdが設定されたので、2FAコードを作成する必要があります。 ターミナルで実行します。

google-authenticator

まず、時間ベースのトークンについて尋ねられます。 この質問にyと答えてください。

Do you want authentication tokens to be time-based: y

画面に大きなQRコードが表示されます。Google Authenticatorアプリでスキャンして追加します。 また、次のようにシークレットといくつかのバックアップコードも表示されます。

Your new secret key is: IRG2TALMR5U2LK5VQ5AQIG3HA4
Your verification code is 282436
Your emergency scratch codes are:
  29778030
  86888537
  50553659
  41403052
  82649596
注記

2FAアプリが手元にない場合にマシンにログインする必要がある場合に備えて、緊急スクラッチコードを安全な場所に記録してください。 アプリがないと、SSHでマシンにログインできなくなります!

最後に、いくつかのパラメータについて尋ねられます。推奨されるデフォルトは次のとおりです。

Do you want me to update your "/<username>/.google_authenticator" file: y
Do you want to disallow multiple uses of the same authentication token: y
By default... < long story about time skew > ... Do you want to do so: n
Do you want to enable rate-limiting: y

完了したら、sshdを再起動して新しい設定を取得します。

sudo systemctl restart sshd

SSHキーでサーバーにSSH接続しようとすると、パスワードは要求されませんが、2FA確認コードも要求されるようになります。

必須: 自動セキュリティ更新を有効にする

オペレーティングシステムベンダーは定期的に更新とセキュリティ修正を公開するため、システムを最新のパッチで最新の状態に保つことが重要です。 これを行う最も簡単な方法は、自動更新を有効にすることです。

ノードマシンで次のコマンドを実行します。

sudo apt update
sudo apt install -y unattended-upgrades update-notifier-common

/etc/apt/apt.conf.d/20auto-upgradesを編集することで、自動更新設定を変更できます。

sudo nano /etc/apt/apt.conf.d/20auto-upgrades

これは、妥当な自動更新設定の例です。

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";

# This is the most important choice: auto-reboot.
# This should be fine since Rocketpool auto-starts on reboot.
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "02:00";

変更の追加が完了したら、Ctrl+OEnterで保存し、Ctrl+Xで終了します。

その後、新しい設定を読み込むことを忘れないでください。

sudo systemctl restart unattended-upgrades

必須: ファイアウォールを有効にする

一般的に、マシンはExecution client、Consensus client、およびSmartnodeスタックが使用するポートでのみネットワークトラフィックを受け入れる必要があります。 それを強制し、予期しない、または望ましくないトラフィックを防ぐために、ノードにファイアウォールをインストールできます。

注記

Rocketpoolセットアップ中に別のexecution/consensus clientポートを選択した場合、以下のポートを設定に合わせて編集する必要があります。

Ubuntuにはデフォルトでufwがインストールされています(uncomplicated fire wall)。これは、ノードのファイアウォール設定を管理するための便利なユーティリティです。

次のコマンドは、Smartnodeの適切なデフォルト構成でufwを設定します。 ノードマシンでこれらを実行してください

明示的に後のルールで許可されていない限り、接続を無効にします。

sudo ufw default deny incoming comment 'Deny all incoming traffic'

SSHを許可します。

sudo ufw allow "22/tcp" comment 'Allow SSH'

execution client(以前はETH1と呼ばれていました)を許可します。

sudo ufw allow 30303/tcp comment 'Execution client port, standardized by Rocket Pool'
sudo ufw allow 30303/udp comment 'Execution client port, standardized by Rocket Pool'

consensus client(以前はETH2と呼ばれていました)を許可します。

sudo ufw allow 9001/tcp comment 'Consensus client port, standardized by Rocket Pool'
sudo ufw allow 9001/udp comment 'Consensus client port, standardized by Rocket Pool'

lighthouse client v4.5.0+を実行している場合、quicプロトコルを使用してレイテンシを削減/帯域幅を増やすことができます。quicプロトコルはデフォルトでlighthouseの--port + 1を使用してquicメッセージをリッスンします: https://lighthouse-blog.sigmaprime.io/Quic,%20Networking.html

sudo ufw allow 8001/udp comment 'Consensus client port, standardised by Rocket Pool'

最後に、ufwを有効にします。

sudo ufw enable
注記

iptablesの専門家は、Dockerがufw設定をバイパスすることに気付くかもしれません。 厳密に言えば、つまりHybridモードで実行していない場合、ExecutionおよびConsensus clientルールは必要ありません。 ただし、それらを追加してもデメリットはなく、Hybridモードに切り替えた場合にファイアウォールの問題が発生しないようにします。

(オプション)ブルートフォースおよびDDoS保護を有効にする

DDoS攻撃やブルートフォース接続試行からサーバーを保護するために、fail2banをインストールできます。 このプログラムは着信接続を監視し、繰り返し誤った資格情報でログインしようとするIPアドレスをブロックします。

侵入防止の詳細については、このガイドを参照してください。

ノードマシンで次のコマンドを実行します。

サービスをインストールします。

sudo apt install -y fail2ban

次に、/etc/fail2ban/jail.d/ssh.localを開きます。

sudo nano /etc/fail2ban/jail.d/ssh.local

次の内容を追加します。

[sshd]
enabled = true
banaction = ufw
port = 22
filter = sshd
logpath = %(sshd_log)s
maxretry = 5

maxretry設定を変更できます。これは、違反アドレスをロックアウトする前に許可する試行回数です。

完了したら、Ctrl+OEnterで保存して終了し、次にCtrl+Xで終了します。

最後に、サービスを再起動します。

sudo systemctl restart fail2ban

これで、ノードのセキュリティ態勢を大幅に改善しました。 おめでとうございます!