自作プロキシ (Nekoxy2) の HTTP/2 (RFC7540) 対応にあたっての私なりの理解をまとめました。
HTTP/2 の解説自体は他サイトのほうがわかりやすかったり正確だったりすると思うので、あくまでも参考程度に。
RFC においては SHOULD とか MUST とかの違いは重要ですが、ここに書くの面倒なので必要に応じて調べましょう。
HPACK(RFC7541) については RFC も別だし長いし記事を分けます。
→ HPACK 理解メモ – CAT EARS
自作プロキシ (Nekoxy2) の HTTP/2 (RFC7540) 対応にあたっての私なりの理解をまとめました。
HTTP/2 の解説自体は他サイトのほうがわかりやすかったり正確だったりすると思うので、あくまでも参考程度に。
RFC においては SHOULD とか MUST とかの違いは重要ですが、ここに書くの面倒なので必要に応じて調べましょう。
HPACK(RFC7541) については RFC も別だし長いし記事を分けます。
→ HPACK 理解メモ – CAT EARS
.NET Core 3.0 Preview 4 で HttpClient
の HTTP/2 サポートが追加されたようですね。
Announcing .NET Core 3 Preview 4 | .NET Blog
今までの .NET Standard では SslStream 自体が HTTP/2 の事実上必須な機能(ALPN)に対応しておらず、.NET Standard 2.1 でようやくサポートされる見込みだったため、どうやらちゃんとくるようで一安心というところです。
(HttpClient
についてはこれのせいかは不明ですが…… SocketsHttpHandler
が HTTP/2 対応していなかったのは確か)
しかしながら .NET Framework 4.8 の方は .NET Standard 2.0 止まりになることになっているので、HTTP/2 サポートは今後あるのかどうかすら怪しいですね……
Given many of the API additions in .NET Standard 2.1 require runtime changes in order to be meaningful, .NET Framework 4.8 will remain on .NET Standard 2.0 rather than implement .NET Standard 2.1.
Announcing .NET Standard 2.1 | .NET Blog
とはいえ .NET Standard はあくまでも API 標準を定めただけで実装は各プラットフォーム依存ですから、動くようになる可能性はあるかも?
とりあえず .NET Framework は 4.8 の時点では HttpClient
+ HttpClientHandler
では動作しそうにありません。
BCL 以外でなら WinHttpHandler を使い、HttpRequestMessage
のバージョンを明示的に指定することで、利用できます(Win10 1607↑ + .NET FW 4.6↑ に限る)。
参考: How to make the .net HttpClient use http 2.0?
実は Core 2.0 までも Windows 環境に限れば WinHttpHandler に丸投げしていたようで、HttpClient
で HTTP/2 が動作します。
Core 2.1 以降 SocketsHttpHandler に移行し、環境依存を減らした為、HTTP/2 に一時的に非対応となっていたようです。
※TCP は詳しくないので間違いあるかも
記事のメモ。
Windows の HTTP スタックには他にも HTTP.sys があるが、基本 IIS 向けのカーネルモードドライバとして動作する HTTP リスナーで、クライアントアプリには超使いにくいやつなんで今回は省略。
なお .NET Framework の System.Net.HttpListener の中身は HTTP.sys なので、アレもサーバー以外では超絶使いにくい。
さて巷ではJVNVU#98282440: 「提督業も忙しい!」(KanColleViewer) がオープンプロキシとして動作する問題が話題ですが、FiddlerCore は何も考えないで実装すると恐らくこうしてしまうような仕様です。クソですね。。
とりあえず適当に FiddlerCore を使ったアプリケーションを立ち上げてみましょう。
[csharp]
FiddlerApplication.Startup(55555, FiddlerCoreStartupFlags.Default);
[/csharp]
するとあら不思議、0.0.0.0:55555でListningされてしまいます。
[raw]
C:\Windows\system32>netstat -a -b -n -o -p TCP
アクティブな接続
プロトコル ローカル アドレス 外部アドレス 状態 PID
…(中略)…
TCP 0.0.0.0:55555 0.0.0.0:0 LISTENING 6688
[FiddlerTest.vshost.exe]
[/raw]
これではアプリが立ち上がってる間は外部からHTTPプロキシとして利用できてしまいます。
知らず知らずのうちに他所様への攻撃の踏み台にされて、ある日突然警察がやってくるなんてこともあるかもしれません。怖いですね。
で、どうすればいいかというと、127.0.0.1:55555でLisningするようにできればローカルプロセスしかアクセスできなくなるので、そう変更したいですね?
これはごく簡単で、AllowRemoteClients
をfalse
にしてやればOKです。
[csharp]
FiddlerApplication.Startup(55555
, FiddlerCoreStartupFlags.RegisterAsSystemProxy
| FiddlerCoreStartupFlags.ChainToUpstreamGateway
| FiddlerCoreStartupFlags.MonitorAllConnections
| FiddlerCoreStartupFlags.CaptureLocalhostTraffic);
[/csharp]
Flagなので指定しなければOK。
[raw]
C:\Windows\system32>netstat -a -b -n -o -p TCP
アクティブな接続
プロトコル ローカル アドレス 外部アドレス 状態 PID
…(中略)…
TCP 127.0.0.1:55555 0.0.0.0:0 LISTENING 7128
[FiddlerTest.vshost.exe]
[/raw]
つまりFiddlerCoreStartupFlags.Default
がイカンわけです。
でも FiddlerCore は Fiddler.exe のUI以外の部分を抜き出したものなわけですから、Fiddler.exe 自体がそういうもんだという可能性もあります。
参照: FiddlerCore – Fiddler Proxy Engine for your .NET Applications
ここで Fiddler.exe および FiddlerCore のデフォルト値を見てみましょう。
WindowsでVPN接続すると、VPN接続先がデフォルトゲートウェイとなるようなルールがルーティングテーブルに追加される。
VPN経由でインターネット接続できる場合は特に問題ないが、そうでない場合はVPN接続中はインターネットが利用できなくなってしまう。
以下の設定により、VPN接続先をデフォルトゲートウェイとするルーティングルールの追加が行われなくなり、VPNのサブネット以外への通信はVPNを経由せず直接インターネット接続するようになる。
powercfg -setdcvalueindex 381b4222-f694-41f0-9685-ff5bb260df2e 19cbb8fa-5279-450e-9fac-8a3d5fedd0c1 12bbebe6-58d6-4636-95bb-3217ef867c1a 0
パラメータ | 説明 |
---|---|
-setdcvalueindex | バッテリ駆動 時の設定 |
381b4222-f694-41f0-9685-ff5bb260df2e | バランス プラン |
19cbb8fa-5279-450e-9fac-8a3d5fedd0c1 | ワイヤレス アダプターの設定 |
12bbebe6-58d6-4636-95bb-3217ef867c1a | 省電力モード |
0 | 最大パフォーマンス(1~3は省電力 (低/中/高)) |
消えた。
参考リンク以上のことは特に調べていないけど、覚え書き。
モジュール有効化
LoadModule authnz_ldap_module modules/mod_authnz_ldap.so LoadModule ldap_module modules/mod_ldap.so
認証設定
AuthType Basic AuthName "auth example" AuthBasicProvider ldap AuthLDAPUrl "ldap://domaincontroller.domainname.local:3268/DC=domainname,DC=local?sAMAccountName?sub?(objectClass=*)" AuthzLDAPAuthoritative Off AuthLDAPBindDn "domainuser" AuthLDAPBindPassword "password" Require valid-user
basedn : 検索の起点となる識別名(DN)を指定します。
attribute : 検索対象の属性です。sAMAccountNameはWindowsのログイン名になります。
scope : 検索する深さを指定します。one(1階層のみ検索)またはsub(下位の階層も検索)です。
filter : 検索のLDAPフィルターです。(objectClass=*)となっているのでツリー上の全てのオブジェクトを検索します。
portをActiveDirectoryのグローバルカタログ(ポート3268)にすれば、basednでOUを指定しなくてもディレクトリ全体が検索範囲になることが分かりました。(グローバルカタログはフォレスト内の全ドメインの全オブジェクトから、ひんぱんに利用する属性のみを抽出したものです。)
Active Directoryでは、標準的な構成の場合認証前に権限のあるユーザで接続をしなければいけません。 そのユーザ名とパスワードをAuthLDAPBindDN、AuthLDAPBindPasswordで指定します。
require valid-user を指定するには、authz_user_moduleのロードとAuthzLDAPAuthoritative Offが必要。
require ldap-userとかならこれらは必要ない。
こんな感じで実行できる。
[raw title=”example.script”]
option batch abort
option confirm off
open ftp://username:password@hostname -explicittls -certificate=”…”
get /example/* c:\example\
exit
[/raw]