WindowsサーバでSSM Agentのプロキシ設定を検証してみた

2022.08.26

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

WindowsサーバーとSSM Agentのプロキシ設定に触る機会があったのでブログに残そうと思います。

SSM Agentとは

SSM AgentはEC2やオンプレミスのサーバにインストールしてSystems Managerで管理できるようにするソフトウェアです。
Systems Managerで管理することでSSHを利用せずにターミナルに接続できたり、Run Commandという機能を利用すればシェルにアクセスすることなくコマンドを実行することも可能になります。
SSM Agent について

検証環境構成

プロキシサーバ

OS:Amazon Linux2
AMI:ami-0ecb2a61303230c9d
プロキシサーバ:Squid

Windowsサーバ

OS:Microsoft Windows Server 2019
AMI:ami-04ac1ccf3fe61134b

構成図


プライベートサブネットに配置されたWindowsサーバからSystems Managerへ通信するのにプロキシサーバを経由する構成になっています。

プロキシサーバの作成

プロキシサーバの作成は以下のブログを参考にさせていただきました。
Squidで検証用のプロキシを作ってみた
以下のコマンドを実行してSquidをインストールします。

sudo yum update
sudo yum install squid

設定ファイルは以下のディレクトリにあるsquid.confになります。

ls -la /etc/squid/
total 60
drwxr-xr-x  2 root root    192 Aug 18 06:03 .
drwxr-xr-x 82 root root   8192 Aug 18 06:04 ..
-rw-r--r--  1 root squid   692 Apr 12  2021 cachemgr.conf
-rw-r--r--  1 root root    692 Apr 12  2021 cachemgr.conf.default
-rw-r--r--  1 root root   1817 Apr 12  2021 errorpage.css
-rw-r--r--  1 root root   1817 Apr 12  2021 errorpage.css.default
-rw-r--r--  1 root root  12077 Apr 12  2021 mime.conf
-rw-r--r--  1 root root  12077 Apr 12  2021 mime.conf.default
-rw-r-----  1 root squid  2315 Apr 12  2021 squid.conf
-rw-r--r--  1 root root   2315 Apr 12  2021 squid.conf.default

中身は以下のようになっています。

#
# Recommended minimum configuration:
#

# Example rule allowing access from your local networks.
# Adapt to list your (internal) IP networks from where browsing
# should be allowed
acl localnet src 10.0.0.0/8     # RFC1918 possible internal network
acl localnet src 172.16.0.0/12  # RFC1918 possible internal network
acl localnet src 192.168.0.0/16 # RFC1918 possible internal network
acl localnet src fc00::/7       # RFC 4193 local private network range
acl localnet src fe80::/10      # RFC 4291 link-local (directly plugged) machines

acl SSL_ports port 443
acl Safe_ports port 80          # http
acl Safe_ports port 21          # ftp
acl Safe_ports port 443         # https
acl Safe_ports port 70          # gopher
acl Safe_ports port 210         # wais
acl Safe_ports port 1025-65535  # unregistered ports
acl Safe_ports port 280         # http-mgmt
acl Safe_ports port 488         # gss-http
acl Safe_ports port 591         # filemaker
acl Safe_ports port 777         # multiling http
acl CONNECT method CONNECT

#
# Recommended minimum Access Permission configuration:
#
# Deny requests to certain unsafe ports
http_access deny !Safe_ports

# Deny CONNECT to other than secure SSL ports
http_access deny CONNECT !SSL_ports

# Only allow cachemgr access from localhost
http_access allow localhost manager
http_access deny manager

# We strongly recommend the following be uncommented to protect innocent
# web applications running on the proxy server who think the only
# one who can access services on "localhost" is a local user
#http_access deny to_localhost

#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#

# Example rule allowing access from your local networks.
# Adapt localnet in the ACL section to list your (internal) IP networks
# from where browsing should be allowed
http_access allow localnet
http_access allow localhost

# And finally deny all other access to this proxy
http_access deny all

# Squid normally listens to port 3128
http_port 3128

# Uncomment and adjust the following to add a disk cache directory.
#cache_dir ufs /var/spool/squid 100 16 256

# Leave coredumps in the first cache dir
coredump_dir /var/spool/squid

#
# Add any of your own refresh_pattern entries above these.
#
refresh_pattern ^ftp:           1440    20%     10080
refresh_pattern ^gopher:        1440    0%      1440
refresh_pattern -i (/cgi-bin/|\?) 0     0%      0
refresh_pattern .               0       20%     4320

Squid configuration directives こちらのドキュメントを読むと「acl 定義名」でアクセスされるポート番号やIPアドレスを記載して「http_access」で拒否するか許可するか設定しているようです。
今回は設定を変更せずに利用します。(15行目と17行目でhttp、httpsが設定されているため)

SSM Agentのプロキシ設定

以下の公式ドキュメントにも設定方法が記載されています。
SSM Agent が Windows Server インスタンス用にプロキシを使用するように設定する
WindowsのSSM Agentのプロキシ設定はWinHTTPやインターネットオプションに設定してもプロキシさせることが可能です。
以下の優先度でプロキシの設定が読み込まれます。

  1. AmazonSSMAGent レジストリ設定 (HKLM:\SYSTEM\CurrentControlSet\Services\AmazonSSMAgent)
  2. システム環境変数 (http_proxy、https_proxy、no_proxy)
  3. LocalSystem ユーザーアカウントの環境変数 (http_proxy、https_proxy、no_proxy)
  4. Internet Explorer の設定 (HTTP、セキュア、例外)
  5. WinHTTP プロキシ設定 (http=、https=、bypass-list=)

上から順に設定を試してみました。

AmazonSSMAGent レジストリ設定 (HKLM:\SYSTEM\CurrentControlSet\Services\AmazonSSMAgent)

WindowsサーバにアクセスしてPowerShellを開いて以下のコマンドを実行します。
※3行目のhostnameとportとなっている部分はプロキシサーバのIPアドレスとポート番号を記載してください。

$serviceKey = "HKLM:\SYSTEM\CurrentControlSet\Services\AmazonSSMAgent"
$keyInfo = (Get-Item -Path $serviceKey).GetValue("Environment")
$proxyVariables = @("http_proxy=hostname:port", "https_proxy=hostname:port", "no_proxy=169.254.169.254")

if ($keyInfo -eq $null) {
    New-ItemProperty -Path $serviceKey -Name Environment -Value $proxyVariables -PropertyType MultiString -Force
} 
else {
    Set-ItemProperty -Path $serviceKey -Name Environment -Value $proxyVariables
}

Restart-Service AmazonSSMAgent

実行後SSM Agentが再起動されるので以下のコマンドで設定内容を確認します。

Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\AmazonSSMAgent"

以下の結果が出力されます。 12行目のEnvironmentに設定したプロキシサーバのIPとポート番号が入っています。

Version                          : 3.1.1634.0
DependOnService                  : Winmgmt
Type                             : 16
Start                            : 2
ErrorControl                     : 1
ImagePath                        : "C:\Program Files\Amazon\SSM\amazon-ssm-agent.exe"
DisplayName                      : Amazon SSM Agent
ObjectName                       : LocalSystem
Description                      : Amazon SSM Agent
FailureActions                   : {128, 81, 1, 0...}
FailureActionsOnNonCrashFailures : 1
Environment                      : {http_proxy=hostname:port, https_proxy=hostname:port, no_proxy=169.254.169.254}
PSPath                           : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AmazonSSMAgent
PSParentPath                     : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
PSChildName                      : AmazonSSMAgent
PSDrive                          : HKLM
PSProvider                       : Microsoft.PowerShell.Core\Registry

この状態でプロキシサーバのログを見てみます。
プロキシサーバにアクセスして以下のコマンドを実行します。

tail -f /var/log/squid/access.log

しばらく待つとSystems Managerへ通信をしているログが流れてきます。

1661410651.917   9105 X.X.X.X TCP_TUNNEL/200 5953 CONNECT ssm.ap-northeast-1.amazonaws.com:443 - HIER_DIRECT/52.119.223.48 -
1661410659.787  20027 X.X.X.X TCP_TUNNEL/200 5919 CONNECT ec2messages.ap-northeast-1.amazonaws.com:443 - HIER_DIRECT/54.240.225.173 -

設定の削除は以下のコマンドをPowerShellで実行します。

Remove-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\AmazonSSMAgent -Name Environment
Restart-Service AmazonSSMAgent

SSM Agent再起動後レジストリ設定を確認すると以下の通りEnvironmentが消えていることがわかります。

Version                          : 3.1.1634.0
DependOnService                  : Winmgmt
Type                             : 16
Start                            : 2
ErrorControl                     : 1
ImagePath                        : "C:\Program Files\Amazon\SSM\amazon-ssm-agent.exe"
DisplayName                      : Amazon SSM Agent
ObjectName                       : LocalSystem
Description                      : Amazon SSM Agent
FailureActions                   : {128, 81, 1, 0...}
FailureActionsOnNonCrashFailures : 1
PSPath                           : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AmazonSSMAgent
PSParentPath                     : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
PSChildName                      : AmazonSSMAgent
PSDrive                          : HKLM
PSProvider                       : Microsoft.PowerShell.Core\Registry

システム環境変数 (http_proxy、https_proxy、no_proxy)

Windowsサーバにアクセスしてコントロールパネル->システムとセキュリティ->システム->システムの詳細設定->環境変数->システム環境変数の新規を開いて環境変数を設定します。
設定する変数は「https_proxy」「http_proxy」「no_proxy」になります。

開いたら変数名に「https_proxy」変数値に「hostname:port」を入力してOKをクリックします。(hostname:portはプロキシサーバのIPアドレスとポート番号を入力します)
もう一度新規を開いて変数名に「http_proxy」変数値に「hostname:port」を入力してOKをクリックします。
「no_proxy」の場合は変数値に「169.254.169.254」を入力します。
最終的には以下の画像のように登録されていれば完了です。

「https_proxy」でhttps要求に使用するプロキシサーバの指定、「http_proxy」でhttp要求に使用するプロキシサーバの指定、「no_proxy」でプロキシから除外するIPを設定しています。
169.254.169.254はEC2のメタデータにアクセスするのに使用するIPアドレスです。SSM AgentがメタデータにアクセスしてEC2のデータを取得するためプロキシさせないように設定を入れます。
設定が完了したら以下のコマンドをPowerShellで実行します。

Restart-Service AmazonSSMAgent

SSM Agentの再起動が完了したらプロキシサーバのログを見てみます。
プロキシサーバにアクセスして以下のコマンドを実行します。

tail -f /var/log/squid/access.log

しばらく待つとSystems Managerへ通信をしているログが流れてきます。

1661413086.564  20037 X.X.X.X TCP_TUNNEL/200 5919 CONNECT ec2messages.ap-northeast-1.amazonaws.com:443 - HIER_DIRECT/54.240.225.173 -
1661413100.200   9081 X.X.X.X TCP_TUNNEL/200 5953 CONNECT ssm.ap-northeast-1.amazonaws.com:443 - HIER_DIRECT/52.119.221.73 -

設定の削除は「https_proxy」「http_proxy」「no_proxy」を選択して「削除」をクリックすると削除されます。

環境変数削除後、以下のコマンドをPowerShellで実行します。

Restart-Service AmazonSSMAgent

LocalSystem ユーザーアカウントの環境変数 (http_proxy、https_proxy、no_proxy)

WindowsのSSM AgentはSYSTEMユーザというものが動かしているためAdministratorユーザの環境変数にプロキシ設定を入れても読み込まれません。
以下の画像のようにSYSTEMユーザが動かしています。

SYSTEMユーザにはAdministratorユーザのようにサインインして設定を行うということはできないのでPsExecというものをダウンロードします。
PsExecを利用することでSYSTEMユーザでプログラムを実行できるようになります。
Windowsサーバにダウンロードして解凍します。
解凍後PowerShellを起動してPsExecのあるフォルダに移動して以下のコマンドを実行します。
以下のコマンドを実行するとSYSTEMユーザでPowerShellが実行されます。

./PsExec.exe -s -i powershell.exe

SYSTEMユーザで実行されたPowerShellで以下のコマンドを実行します。(hostnameとportとなっている部分はプロキシサーバのIPアドレスとポート番号を記載してください。)

[Environment]::SetEnvironmentVariable("https_proxy", "hostname:port", [System.EnvironmentVariableTarget]::User)
[Environment]::SetEnvironmentVariable("http_proxy", "hostname:port", [System.EnvironmentVariableTarget]::User)
[Environment]::SetEnvironmentVariable("no_proxy", "169.254.169.254", [System.EnvironmentVariableTarget]::User)
Restart-Service AmazonSSMAgent

SSM Agentの再起動が完了したら以下のコマンドで設定を確認できます。

[Environment]::GetEnvironmentVariable("https_proxy","User")
[Environment]::GetEnvironmentVariable("http_proxy","User")
[Environment]::GetEnvironmentVariable("no_proxy","User")

この状態でプロキシサーバにアクセスして以下のコマンドを実行します。

tail -f /var/log/squid/access.log

以下のようにログが流れてきていれば設定完了です。

1661418432.079   9065 X.X.X.X TCP_TUNNEL/200 5953 CONNECT ssm.ap-northeast-1.amazonaws.com:443 - HIER_DIRECT/52.119.221.73 -
1661418435.763  20038 X.X.X.X TCP_TUNNEL/200 5919 CONNECT ec2messages.ap-northeast-1.amazonaws.com:443 - HIER_DIRECT/54.240.225.178 -

設定の削除は以下のコマンドをSYSTEMユーザで実行されたPowerShellで実行します。

[Environment]::SetEnvironmentVariable("https_proxy", "", [System.EnvironmentVariableTarget]::User)
[Environment]::SetEnvironmentVariable("http_proxy", "", [System.EnvironmentVariableTarget]::User)
[Environment]::SetEnvironmentVariable("no_proxy", "", [System.EnvironmentVariableTarget]::User)
Restart-Service AmazonSSMAgent

Internet Explorer の設定 (HTTP、セキュア、例外)

こちらの設定もSYSTEMユーザで設定を行うためPsExecを利用します。
PsExecのあるフォルダに移動して以下のコマンドを実行します。

./PsExec.exe -s -i "C:\Program Files\Internet Explorer\iexplore.exe"

コマンドを実行するとInternet Explorerが起動します。
起動したらツール->インターネットオプション->接続->LANの設定を開きます。




LANの設定を開いたら「LANにプロキシサーバーを使用する」にチェックを入れ、詳細設定を開きます。

詳細設定を開いたら以下の画像のように設定を入力していきます。
入力する部分は「HTTP(H)」「Secure(S)」「次で始まるアドレスにはプロキシを使用しない(N)」になります。
入力値はプロキシサーバのIPアドレス、ポート番号、EC2のメタデータにアクセスするためのIPアドレスになります。

入力が完了したらOKをクリックしてPowerShellで以下のコマンドを実行します。

Restart-Service AmazonSSMAgent

SSM Agentの再起動が完了したらプロキシサーバにアクセスして以下のコマンドを実行します。

tail -f /var/log/squid/access.log

以下のようにログが流れてきていれば設定完了です。

1661421159.845  12701 X.X.X.X TCP_TUNNEL/200 6271 CONNECT ssm.ap-northeast-1.amazonaws.com:443 - HIER_DIRECT/52.119.221.73 -
1661421169.898  19918 X.X.X.X TCP_TUNNEL/200 5576 CONNECT ec2messages.ap-northeast-1.amazonaws.com:443 - HIER_DIRECT/54.240.225.173 -

設定の削除はSYSTEMユーザで起動したInternet Explorerでツール->インターネットオプション->接続->LANの設定を開きプロキシの設定で入力した値を削除してPowerShellで以下のコマンドを実行します。

Restart-Service AmazonSSMAgent

WinHTTP プロキシ設定 (http=、https=、bypass-list=)

PowerShellを開いて以下のコマンドを実行します。(hostname:portはプロキシサーバのIPアドレスとポート番号を入力します)
proxy-serverでhttpとhttpsで利用するプロキシサーバを指定して、bypass-listでプロキシサーバを利用しないIPアドレスを指定します。
Netsh Commands for Windows Hypertext Transfer Protocol (WINHTTP)

netsh winhttp set proxy proxy-server="http=hostname:port;https=hostname:port" bypass-list="169.254.169.254"
Restart-Service AmazonSSMAgent

実行後、以下のコマンドで設定を確認します。

netsh winhttp show proxy

結果は以下のように出力されます。

Current WinHTTP proxy settings:

    Proxy Server(s) :  http=hostname:port;https=hostname:port
    Bypass List     :  169.254.169.254

この状態でプロキシサーバにアクセスして以下のコマンドを実行します。

tail -f /var/log/squid/access.log

以下のようにログが流れてきていれば設定完了です。

1661422045.974   9099 X.X.X.X TCP_TUNNEL/200 5953 CONNECT ssm.ap-northeast-1.amazonaws.com:443 - HIER_DIRECT/52.119.219.52 -
1661422064.604  20031 X.X.X.X TCP_TUNNEL/200 5919 CONNECT ec2messages.ap-northeast-1.amazonaws.com:443 - HIER_DIRECT/54.240.225.173 -

設定の削除は以下のコマンドをPowerShellで実行します。

netsh winhttp reset proxy
Restart-Service AmazonSSMAgent

設定が消えていることを以下のコマンドで確認して完了です。

netsh winhttp show proxy

消えている場合は以下のように出力されます。

Current WinHTTP proxy settings:

    Direct access (no proxy server).

さいごに

今回はWindowsサーバのSSM Agentプロキシ設定を検証してみました。
プロキシの設定方法が多いので「設定を削除してもプロキシを経由している」や「設定をしたのにSSMで接続ができない」などがあった場合に全ての設定を確認する必要があります。
基本的にはSSM Agentのレジストリに設定する方法で良いと思いました。