「Windows L2TP/IPSec VPN接続時のAssumeUDPEncapsulationContextOnSendRuleについて」でNVR500 L2TP/IPsec VPNサーバにWindows L2TP/IPsec接続すると「NAT/NAPT」が介在していなくても「NAT/NAPT」を誤検出する原因をWiresharkで調べてみた。
1)「AssumeUDPEncapsulationContextOnSendRule=(dword) 0x0」を確認
設定変更後、再起動が必要。
2)NVR500の暗号キーが正しく出力される条件に変更
「Win10 VPN接続時のNVR500 L2TP/IPsec ISAKMP復号鍵が壊れて表示」されるため、Windows L2TP/IPsec VPNの暗号化キーを「ISAKMP=AES256/SHA256/PFS2048/Group14」「ESP=AES128/SHA1」に変更する
NVR500の暗号化キーも変更する
3)Wiresharkで解析
「ヤマハNVR500のL2TP/IPsec VPNパケットをWiresharkで解析」の「Wiresharkでキャプチャ作業」を実施。
Initiator(Windows端末側)からNAT-Dの対応方式を提示
Responder(NVR500側)が方式を決定(RFC 3947 Negotiation of NAT-Traversal in the IKE)
InitiatorとResponderで接続時のIPアドレスとポート番号をNAT-Dで相互に通知し、NAT/NAPTの存在を確認する
RFC3947によれば、IPアドレスとポート番号をinitiatorSPIとresponderSPIと共にISAKMPで合意したSHA256でhash化し、NAT/NAPTの有無を検出する。
hash値=HASH( CKY-I | CKY-R | IP | Port )
1番目に相手側のNAT-D情報。2番目以降に自端末側のNAT-D情報を通知する。自端末に複数アドレスが設定されている場合は、それぞれのNAT-D情報を3番目以降に通知しても良い。
InitiatorでResponderのIPアドレスとポート番号のNAT-D情報
正しく通知されているかhash情報を確認してみる。
Wiresharkの「Packet Details」表示で
「Internet Security Association and Key Management Protocol」セクションの「Initiator SPI」「Responder SPI」をそれぞれ選択し、「Export Packet Bytes...」で「iSPI.bin」「rSPI.bin」としてファイル化する。
「Internet Protocol Version 4, Src: 172.24.1.80, Dst: 172.24.1.2」セクションで「Source 」からInitiatorアドレス「172-24-1-80.bin」、「Destination」からResponderアドレス「172-24-1-2.bin」をファイル化する。
「User Datagram Protocol, Src Port: 500, Dst Port: 500」セクションの「Source Port」からInitiatorポート「iPort.bin」、「Destination Port」からResponderポート「rPort.bin」をファイル化する。
hash化するため、「iSPI.bin」「rSPI.bin」「172-24-1-2.bin」「rPort.bin」のバイナリーファイルを結合し「 irSPI-172-24-1-2-rPort.bin」とする。
結合した「 irSPI-172-24-1-2-rPort.bin」ファイルからsha256でhash値を生成する
Initiator側(Windows端末)で生成されたNAT-D hash値と一致。
InitiatorでInitiatorのIPアドレスとポート番号のNAT-D情報
hash化するため、「iSPI.bin」「rSPI.bin」「172-24-1-80.bin」「iPort.bin」のバイナリーファイルを結合し、「 irSPI-172-24-1-80-iPort.bin」とする。
hash値を生成する
Initiator側(Windows端末)で生成されたNAT-D hash値と一致。
Responder(NVR500)側で生成されるNAT-D情報を確認する
ResponderでInitiatorのIPアドレスとポート番号のNAT-D情報
「Internet Protocol Version 4, Src: 172.24.1.2, Dst: 172.24.1.80」セクションからInitiatorアドレスは、「Destination」値を「172-24-1-80.bin」名でファイル化。
「User Datagram Protocol, Src Port: 500, Dst Port: 500」セクションからInitiatorポート番号は、「Destination Port」値を「iPort.bin」名でファイル化。結合して「irSPI-172-24-1-80-iPort.bin」とする。
hash値を生成する
Responder(NVR500)側で生成されたNAT-D hash値と一致。
ResponderでResponderのIPアドレスとポート番号のNAT-D情報
「Internet Protocol Version 4, Src: 172.24.1.2, Dst: 172.24.1.80」セクションからResponderアドレスは、「Source」値を「172-24-1-2.bin」名でファイル化。
「User Datagram Protocol, Src Port: 500, Dst Port: 500」セクションからResponderポート番号は、「Source Port」値を「rPort.bin」名でファイル化。結合して「irSPI-172-24-1-2-rPort.bin」とする。
hash値を生成する
Responder(NVR500)側で生成されたNAT-D hash値と一致しない。
NVR500は、Responderアドレス及びポートが「172.24.1.2」及び「500」と認識していない?。
間違える可能性は、「Secondary address」と「Primary address」を取り違えた。
可能性を検証するため「Primary address」でhash値を生成してみた。
「Primary address」は、DHCPで「192.168.1.51」が設定されている。バイナリーでファイル化し「192-168-1-51.bin」として生成。
「iSPI.bin」「rSPI.bin」「192-168-1-51.bin」「iPort.bin」を結合し「irSPI-192-168-1-51-iPort.bin」とする。
hash値を生成
Responder(NVR500)側で生成されたNAT-D hash値と一致する。
「Windows L2TP/IPSec VPN接続時のAssumeUDPEncapsulationContextOnSendRuleについて」の「NVR500 system.log(debug on)」で「2019/09/14 23:03:11: [IKE] NAT Traversal: NAT box detected, start keepalive timer」となる原因と思われる。
NVR500の間違ったNAT-D(20)による接続断の理由を検討する
ISAKMPのパケット#3から#8までNAT-Traversal関連情報を「RFC3947」と「Traveling a NAT」を参考にまとめてみた
パケット#3,4のNAT-DとSource/Destination IPアドレスとポートからサーバ側にアドレス変換NATの存在が判断される。
パケット#5,6でポート4500/udpへの切替(ここから暗号化)。パケット#7,8で「UDP-Encapsulation-Transport」が選択される。
Initiator(win10)側は、「AssumeUDPEncapsulationContextOnSendRule=0」なので「サーバのNAT背後を許可しない」。結果接続に失敗する。
「AssumeUDPEncapsulationContextOnSendRule=1」の場合
「サーバのNAT背後を許可」
接続される
「AssumeUDPEncapsulationContextOnSendRule=2」の場合
「サーバ及びクライアントのNAT背後を許可」
接続される
「AssumeUDPEncapsulationContextOnSendRule=0」でNATが存在している場合
win10(172.24.1.80) <-> NVR500(IPv4 over IPv6)<-> Transix DS-Lite(217.178.25.161:12554)<-> Plala IPv4 PPPoE <-> NVR500 L2TP/IPsec VPNサーバ(114.183.167.149:500)
パケット#3,4でクライアント側がNAT背後にある事が判る。パケット#5,6でポート4500/udpに変更し接続(暗号化)。サーバがNAT(1:1)で接続されていることが推定される。パケット#7,8で「UDP-Encapsulation-Transport」が選択される。サーバがNAT背後に無いので、「AssumeUDPEncapsulationContextOnSendRule=0」でも接続される。
4)結果
NVR500のL2TP/IPsec VPN接続でSecondary IP addressがVPNサーバアドレスに設定されているとNAT-Discoveryでhash値計算対象がPrimary IP addressを使用してしまい、サーバ側にNATが存在しなくても、サーバがNAT背後に設置されている状態となる。静的NATが設定されている場合は、未確認。
Windows L2TP/IPsec VPNでは、「AssumeUDPEncapsulationContextOnSendRule=0」(デフォルト)のため接続出来ない。
「0x1」または「0x2」に設定する必要がある。
macOS(10.14.6)Mojaveでは、接続出来る。
1)「AssumeUDPEncapsulationContextOnSendRule=(dword) 0x0」を確認
設定変更後、再起動が必要。
2)NVR500の暗号キーが正しく出力される条件に変更
「Win10 VPN接続時のNVR500 L2TP/IPsec ISAKMP復号鍵が壊れて表示」されるため、Windows L2TP/IPsec VPNの暗号化キーを「ISAKMP=AES256/SHA256/PFS2048/Group14」「ESP=AES128/SHA1」に変更する
--- powershell command ---
設定変更
Powershell -Command Set-VpnConnectionIPsecConfiguration -AuthenticationTransformConstants SHA1 -CipherTransformConstants AES128 -ConnectionName 'test L2TP ipsec' -DHGroup Group14 -EncryptionMethod AES256 -IntegrityCheckMethod SHA256 -PfsGroup PFS2048
設定内容を確認
Powershell -Command (Get-VpnConnection -Name 'test L2TP ipsec').IPSecCustomPolicy
初期値に戻す
Powershell -Command Set-VpnConnectionIPsecConfiguration -ConnectionName 'test L2TP ipsec' -RevertToDefault
----------------
ipsec sa policy policy_id gateway_id esp aes-cbc sha-hmac
3)Wiresharkで解析
「ヤマハNVR500のL2TP/IPsec VPNパケットをWiresharkで解析」の「Wiresharkでキャプチャ作業」を実施。
Initiator(Windows端末側)からNAT-Dの対応方式を提示
Responder(NVR500側)が方式を決定(RFC 3947 Negotiation of NAT-Traversal in the IKE)
InitiatorとResponderで接続時のIPアドレスとポート番号をNAT-Dで相互に通知し、NAT/NAPTの存在を確認する
RFC3947によれば、IPアドレスとポート番号をinitiatorSPIとresponderSPIと共にISAKMPで合意したSHA256でhash化し、NAT/NAPTの有無を検出する。
hash値=HASH( CKY-I | CKY-R | IP | Port )
1番目に相手側のNAT-D情報。2番目以降に自端末側のNAT-D情報を通知する。自端末に複数アドレスが設定されている場合は、それぞれのNAT-D情報を3番目以降に通知しても良い。
InitiatorでResponderのIPアドレスとポート番号のNAT-D情報
正しく通知されているかhash情報を確認してみる。
Wiresharkの「Packet Details」表示で
「Internet Security Association and Key Management Protocol」セクションの「Initiator SPI」「Responder SPI」をそれぞれ選択し、「Export Packet Bytes...」で「iSPI.bin」「rSPI.bin」としてファイル化する。
「Internet Protocol Version 4, Src: 172.24.1.80, Dst: 172.24.1.2」セクションで「Source 」からInitiatorアドレス「172-24-1-80.bin」、「Destination」からResponderアドレス「172-24-1-2.bin」をファイル化する。
「User Datagram Protocol, Src Port: 500, Dst Port: 500」セクションの「Source Port」からInitiatorポート「iPort.bin」、「Destination Port」からResponderポート「rPort.bin」をファイル化する。
hash化するため、「iSPI.bin」「rSPI.bin」「172-24-1-2.bin」「rPort.bin」のバイナリーファイルを結合し「 irSPI-172-24-1-2-rPort.bin」とする。
--- macOS ---
cat iSPI.bin rSPI.bin 172-24-1-2.bin rPort.bin > irSPI-172-24-1-2-rPort.bin
--- windows ---
copy /b iSPI.bin+rSPI.bin+172-24-1-2.bin+rPort.bin irSPI-172-24-1-2-rPort.bin
------
結合した「 irSPI-172-24-1-2-rPort.bin」ファイルからsha256でhash値を生成する
--- macOS ---
shasum -a 256 irSPI-172-24-1-2-rPort.bin
95a5f628e3662bedf1e22cd29091c3355979a16d2a996fea85e5a9fa30ff9c51 irSPI-172-24-1-2-rPort.bin
--- windows ---
CertUtil -hashfile irSPI-172-24-1-2-rPort.bin sha256
SHA256 ハッシュ (対象 irSPI-172-24-1-2-rPort.bin):
95a5f628e3662bedf1e22cd29091c3355979a16d2a996fea85e5a9fa30ff9c51
CertUtil: -hashfile コマンドは正常に完了しました。
------
Initiator側(Windows端末)で生成されたNAT-D hash値と一致。
InitiatorでInitiatorのIPアドレスとポート番号のNAT-D情報
hash化するため、「iSPI.bin」「rSPI.bin」「172-24-1-80.bin」「iPort.bin」のバイナリーファイルを結合し、「 irSPI-172-24-1-80-iPort.bin」とする。
--- macOS ---
cat iSPI.bin rSPI.bin 172-24-1-80.bin iPort.bin > irSPI-172-24-1-80-iPort.bin
--- windows ---
copy /b iSPI.bin+rSPI.bin+172-24-1-80.bin+iPort.bin irSPI-172-24-1-80-iPort.bin
------
hash値を生成する
--- macOS ---
shasum -a 256 irSPI-172-24-1-80-iPort.bin
0a06ad91ca88bdf3814c4f2e1e8c01d8ecdedc6100a99bba7a0f049459b97ab4 irSPI-172-24-1-80-iPort.bin
--- windows ---
CertUtil -hashfile irSPI-172-24-1-80-iPort.bin sha256
SHA256 ハッシュ (対象 irSPI-172-24-1-80-iPort.bin):
0a06ad91ca88bdf3814c4f2e1e8c01d8ecdedc6100a99bba7a0f049459b97ab4
CertUtil: -hashfile コマンドは正常に完了しました。
------
Initiator側(Windows端末)で生成されたNAT-D hash値と一致。
Responder(NVR500)側で生成されるNAT-D情報を確認する
ResponderでInitiatorのIPアドレスとポート番号のNAT-D情報
「Internet Protocol Version 4, Src: 172.24.1.2, Dst: 172.24.1.80」セクションからInitiatorアドレスは、「Destination」値を「172-24-1-80.bin」名でファイル化。
「User Datagram Protocol, Src Port: 500, Dst Port: 500」セクションからInitiatorポート番号は、「Destination Port」値を「iPort.bin」名でファイル化。結合して「irSPI-172-24-1-80-iPort.bin」とする。
hash値を生成する
--- macOS ---
shasum -a 256 irSPI-172-24-1-80-iPort.bin
0a06ad91ca88bdf3814c4f2e1e8c01d8ecdedc6100a99bba7a0f049459b97ab4 irSPI-172-24-1-80-iPort.bin
--- windows ---
CertUtil -hashfile irSPI-172-24-1-80-iPort.bin sha256
SHA256 ハッシュ (対象 irSPI-172-24-1-80-iPort.bin):
0a06ad91ca88bdf3814c4f2e1e8c01d8ecdedc6100a99bba7a0f049459b97ab4
CertUtil: -hashfile コマンドは正常に完了しました。
------
Responder(NVR500)側で生成されたNAT-D hash値と一致。
ResponderでResponderのIPアドレスとポート番号のNAT-D情報
「Internet Protocol Version 4, Src: 172.24.1.2, Dst: 172.24.1.80」セクションからResponderアドレスは、「Source」値を「172-24-1-2.bin」名でファイル化。
「User Datagram Protocol, Src Port: 500, Dst Port: 500」セクションからResponderポート番号は、「Source Port」値を「rPort.bin」名でファイル化。結合して「irSPI-172-24-1-2-rPort.bin」とする。
hash値を生成する
--- macOS ---
shasum -a 256 irSPI-172-24-1-2-rPort.bin
95a5f628e3662bedf1e22cd29091c3355979a16d2a996fea85e5a9fa30ff9c51 irSPI-172-24-1-2-rPort.bin
--- windows ---
CertUtil -hashfile irSPI-172-24-1-2-rPort.bin sha256
SHA256 ハッシュ (対象 irSPI-172-24-1-2-rPort.bin):
95a5f628e3662bedf1e22cd29091c3355979a16d2a996fea85e5a9fa30ff9c51
CertUtil: -hashfile コマンドは正常に完了しました。
------
Responder(NVR500)側で生成されたNAT-D hash値と一致しない。
NVR500は、Responderアドレス及びポートが「172.24.1.2」及び「500」と認識していない?。
間違える可能性は、「Secondary address」と「Primary address」を取り違えた。
可能性を検証するため「Primary address」でhash値を生成してみた。
「Primary address」は、DHCPで「192.168.1.51」が設定されている。バイナリーでファイル化し「192-168-1-51.bin」として生成。
「iSPI.bin」「rSPI.bin」「192-168-1-51.bin」「iPort.bin」を結合し「irSPI-192-168-1-51-iPort.bin」とする。
hash値を生成
--- macOS ---
shasum -a 256 irSPI-192-168-1-51-iPort.bin
e0bccdcaae9fc4898f8236e171340df82cee7fcff4fa3e69d980709f23ae7146 irSPI-192-168-1-51-iPort.bin
--- windows ---
CertUtil -hashfile irSPI-192-168-1-51-iPort.bin sha256
SHA256 ハッシュ (対象 irSPI-192-168-1-51-iPort.bin):
e0bccdcaae9fc4898f8236e171340df82cee7fcff4fa3e69d980709f23ae7146
CertUtil: -hashfile コマンドは正常に完了しました。
------
Responder(NVR500)側で生成されたNAT-D hash値と一致する。
「Windows L2TP/IPSec VPN接続時のAssumeUDPEncapsulationContextOnSendRuleについて」の「NVR500 system.log(debug on)」で「2019/09/14 23:03:11: [IKE] NAT Traversal: NAT box detected, start keepalive timer」となる原因と思われる。
NVR500の間違ったNAT-D(20)による接続断の理由を検討する
ISAKMPのパケット#3から#8までNAT-Traversal関連情報を「RFC3947」と「Traveling a NAT」を参考にまとめてみた
パケット#3,4のNAT-DとSource/Destination IPアドレスとポートからサーバ側にアドレス変換NATの存在が判断される。
パケット#5,6でポート4500/udpへの切替(ここから暗号化)。パケット#7,8で「UDP-Encapsulation-Transport」が選択される。
Initiator(win10)側は、「AssumeUDPEncapsulationContextOnSendRule=0」なので「サーバのNAT背後を許可しない」。結果接続に失敗する。
「AssumeUDPEncapsulationContextOnSendRule=1」の場合
「サーバのNAT背後を許可」
接続される
「AssumeUDPEncapsulationContextOnSendRule=2」の場合
「サーバ及びクライアントのNAT背後を許可」
接続される
「AssumeUDPEncapsulationContextOnSendRule=0」でNATが存在している場合
win10(172.24.1.80) <-> NVR500(IPv4 over IPv6)<-> Transix DS-Lite(217.178.25.161:12554)<-> Plala IPv4 PPPoE <-> NVR500 L2TP/IPsec VPNサーバ(114.183.167.149:500)
パケット#3,4でクライアント側がNAT背後にある事が判る。パケット#5,6でポート4500/udpに変更し接続(暗号化)。サーバがNAT(1:1)で接続されていることが推定される。パケット#7,8で「UDP-Encapsulation-Transport」が選択される。サーバがNAT背後に無いので、「AssumeUDPEncapsulationContextOnSendRule=0」でも接続される。
4)結果
NVR500のL2TP/IPsec VPN接続でSecondary IP addressがVPNサーバアドレスに設定されているとNAT-Discoveryでhash値計算対象がPrimary IP addressを使用してしまい、サーバ側にNATが存在しなくても、サーバがNAT背後に設置されている状態となる。静的NATが設定されている場合は、未確認。
Windows L2TP/IPsec VPNでは、「AssumeUDPEncapsulationContextOnSendRule=0」(デフォルト)のため接続出来ない。
「0x1」または「0x2」に設定する必要がある。
macOS(10.14.6)Mojaveでは、接続出来る。