RDS for SQL Server で rds.force_ssl パラメータ変更時の透過的な暗号化接続の挙動を sqlcmd で確認してみた

2024.05.29

いわさです。

Amazon RDS のエンジンタイプで SQL Server を選択し SSL/TLS 接続を使いたい場面がありました。
クライアント側で SSL/TLS 接続設定が必要だと思っていたのですが、次のドキュメントによるとどうやらクライアント側で明示的な設定が必要な場合と、特にクライアント側で対応は不要で透過的に接続される場合があるということがわかりました。

SSL を使用して SQL Server DB インスタンスに接続する方法は 2 とおりあります。

  • すべての接続に SSL を強制する — これはクライアントに対して透過的に行われ、クライアントは SSL を使用するための作業を行う必要はありません。

  • 特定の接続を暗号化する — 特定のクライアントコンピュータから SSL 接続を確立します。接続を暗号化するためにクライアントで作業を行う必要があります。

rds.force_sslパラメータを設定することで、すべての接続に SSL/TLS を強制することが出来ます。
どうやらその設定をすると、クライアントで特に設定変更を行わずに透過的に行えるとのことです。

上記の透過的な SSL/TLS 接続を sqlcmd を使って確認してみました。

rds.force_ssl がデフォルト(0)の時

クライアントで SSL/TLS 指定なし

デフォルトでは、rds.force_ssl パラメータが 0 (off) に設定されています。
この状態で特にオプションを指定せずに接続してみましょう。

接続後、ENCRYPT_OPTIONで接続ステータスを確認してみましょう。
ENCRYPT_OPTIONは、この接続に対して暗号化が有効になっているかどうかを示すブール値です。
値が TRUE の場合接続は暗号化されており、値が FALSE の場合は接続は暗号化されていません。

% sqlcmd -S hoge0528mssql.cpnu9ipu74g4.ap-northeast-1.rds.amazonaws.com -U admin
Password: 
1> select ENCRYPT_OPTION from SYS.DM_EXEC_CONNECTIONS where SESSION_ID = @@SPID
2> go
ENCRYPT_OPTION                          
----------------------------------------
FALSE                                   

(1 rows affected)

接続が暗号化されていないことがわかりました。

クライアントで SSL/TLS 指定あり

続いて、クライアントから接続を行う際に明示的に暗号化オプションを指定してみましょう。
なお、参考までに sqlcmd のユーティリティは以下になります。

-N は暗号化された接続を要求するオプション、-C はサーバー証明書を検証せずに暗黙的に信頼するようにクライアントを構成するオプションです。
今回の検証ではクライアント側に何も証明書関連のものをセットアップしていないので-Cオプションを指定しています。

% sqlcmd -S hoge0528mssql.cpnu9ipu74g4.ap-northeast-1.rds.amazonaws.com -U admin -N -C
Password: 
1> select ENCRYPT_OPTION from SYS.DM_EXEC_CONNECTIONS where SESSION_ID = @@SPID
2> go
ENCRYPT_OPTION                          
----------------------------------------
TRUE                                    

(1 rows affected)
1>

このオプションを使う場合、つまりクライアントから明示的に暗号化接続を指定する場合は上記のように、接続が暗号化されていることが確認出来ました。
sqlcmd であればデフォルトは暗号化されずに、クライアントから明示的な暗号化接続は可能という状態ですね。

rds.force_ssl が 1 の時

では続いてrds.force_sslの値を変更してみましょう。
次のようにカスタムパラメータグループで値を1に変更しました。

クライアントで SSL/TLS 指定なし

先ほどと同じように特にオプションを指定せずに接続してみます。
ドキュメントのとおり透過的に接続が暗号化されているはず...

% sqlcmd -S hoge0528mssql.cpnu9ipu74g4.ap-northeast-1.rds.amazonaws.com -U admin        
Password: 
1> select ENCRYPT_OPTION from SYS.DM_EXEC_CONNECTIONS where SESSION_ID = @@SPID
2> go
ENCRYPT_OPTION                          
----------------------------------------
FALSE                                   

(1 rows affected)

あれっ...?
よく見たらカスタムパラメータグループのステータスが再起動保留中になっていました。

静的パラメータになるので、RDS インスタンスの再起動が明示的に必要なのを忘れていました。
インスタンスを再起動してもう一度トライしてみます。

% sqlcmd -S hoge0528mssql.cpnu9ipu74g4.ap-northeast-1.rds.amazonaws.com -U admin
Password: 
1> select ENCRYPT_OPTION from SYS.DM_EXEC_CONNECTIONS where SESSION_ID = @@SPID
2> go
ENCRYPT_OPTION                          
----------------------------------------
TRUE                                    

(1 rows affected)
1>

お、今度は透過的に接続が暗号化されましたね。
特にクライアント側で証明書のセットアップはしていませんが。

さいごに

本日は RDS for SQL Server で rds.force_ssl パラメータ変更時の動作を sqlcmd で確認してみました。

ADO.NET クライアントなどからの接続確認なども行いたかったのですが、sqlcmd で挙動の違いをまずは確認出来たので今日のところは一旦ここまでで良いでしょう。
これまではクライアントへ証明書をインポートとして明示的に接続文字列で暗号化接続の指定が必要だと思いこんでいたのですが、カスタムパラメータグループを使うことで、クライアント側の変更は不要で透過的に暗号化を行えることを知りました。