[17] [[プロトコル横断攻撃]]を防止するため、一部の[[ポート]]の [[fetch]]
は禁止されています。これを [DFN[port blocking]] といいます。

* 仕様書

[REFS[
- [16] [CITE@en-US[Fetch Standard]] ([TIME[2016-03-11 02:17:17 +09:00]] 版) <https://fetch.spec.whatwg.org/#port-blocking>
]REFS]

* 悪いポートの判定

[23] [[要求]][VAR[要求]]について [DFN[should be blocked due to a bad port]]
は、次のようにします [SRC[>>16]]。

[FIG(steps)[
= [24] [VAR[URL]] を、[VAR[要求]]の[F[現在URL]]に設定します。
= [25] [VAR[scheme]] を、[VAR[URL]]の[F[scheme][URL scheme]]に設定します。
= [26] [VAR[ポート]]を、 [VAR[URL]]の[F[port]]に設定します。
= [27] [VAR[scheme]] が [CODE(URI)@en[ftp][ftp:]] の場合、
== [29] [VAR[ポート]]が [CODE[20]] か [CODE[21]] なら、「[RUBYB[認められる]@en[allowed]]」
を返し、ここで停止します。
= [30] [VAR[scheme]] が[[ネットワークスキーム]]の場合、
== [28] [VAR[ポート]]が[[悪いポート]]なら、「[RUBYB[妨害される]@en[blocked]]」
を返し、ここで停止します。
= [31] 「[RUBYB[認められる]@en[allowed]]」を返し、ここで停止します。
]FIG]

;; [32] [[WebSocket]] ([VAR[scheme]] が [CODE(URI)@en[ws][ws:]] や
[CODE(URI)@en[wss][wss:]]) は、この判定の時点で 
[CODE(URI)@en[http][http:]] や [CODE(URI)@en[https][https:]]
に書き換えられているので、 [[HTTP]] の制約が適用されます。

;; [33] [[FTP]] から [N[80]] にアクセスすることは認められますが、
[[HTTP]] から [N[20]] や [N[21]] にアクセスすることは禁じられます。

[34] [DFN[[RUBYB[悪いポート]@en[bad port]]]]は、次の[[ポート]]です [SRC[>>16]]。

[FIG(list)[
1 7 9 11 13 15 17 19 20 21 22 23 25 37 42 43 53 77 79 87 95 101 102
103 104 109 110 111 113 115 117 119 123 135 139 143 179 389 427 465 512
513 514 515 526 530 531 532 540 548 556 563 587 601 636 993 995 2049
3659 4045 6000 6665 6666 6667 6668 6669 6697
]FIG]

;; [37] このリストは次の [[JSON]] 形式のデータファイルにも含まれています。
[REFS[
- [35] [CITE@en[data-web-defs/url-schemes.json at master · manakai/data-web-defs]] ([TIME[2016-03-11 21:04:32 +09:00]] 版) <https://github.com/manakai/data-web-defs/blob/master/data/url-schemes.json>
-- [36] ドキュメント [CITE@en[data-web-defs/url-schemes.txt at master · manakai/data-web-defs]] ([TIME[2016-03-11 21:04:53 +09:00]] 版) <https://github.com/manakai/data-web-defs/blob/master/doc/url-schemes.txt>
]REFS]

[48] [[悪いポート]]を[[既定のポート]]とする[[プロトコル]]の多くは、
[[プロトコル横断攻撃]]の危険性が知られる前に作られていて何の対策もしていなかったり、
多くの[[サーバー]]や [[Unix]] 系システムで標準状態で動作していたりして、
[[ポート]]制限がなければ危険であると考えられています。
そうした[[ポート]]で [[HTTP]] を使うことは無いでしょうから、
制限に実害もありません。

[49] 新しい[[プロトコル]]の設計者は、
おそらくこれら以外の[[ポート番号]]を使うこととなるでしょうから、
[[プロトコル横断攻撃]]への対策を考える必要があります。

;; といっても今後新たに設計される [[TCP]] 上のほとんどの[[プロトコル]]は [[TLS]] 
を使うことになるでしょうから、 [[ALPN]] で十分です。

* OS 以遠の制限

[11] [[Webブラウザー]]独自の制限に加えて、 [[OS]] の[[ネットワークスタック]]レベルでの
([[利用者]]や管理者の設定による) 制限があるかもしれません。

[12] 所属[[ネットワーク]]などの ([[ルーター]]等の) 制限で、接続できない[[ポート]]があるかもしれません。

[EG[
[43] 残念なことに、こんにちの多くの [[ISP]] は [[OP25B]] を実施しています。
]EG]

[EG[
[45] 組織のネットワークでは、 [N[80]] と [N[443]] とその他少数の[[ポート]]以外の利用を禁止していることがあります。

;; [46] このような制限は[[Web互換]]ではありませんが、現にそうした[[ネットワーク]]が少なからず存在している以上、
[[著者]]は [N[80]] と [N[443]] 以外使うべきではありません。
]EG]

[13] こうした制限は、実際に接続を試みないと[[Webブラウザー]]からは検知できませんから、
[[OS]] に接続の開始を指示した後、拒まれたとのエラーになったり、
接続を開始した後にタイムアウトで[[ネットワークエラー]]となったりします。

[47] 制限の実装方法にもよりますが、[[タイムアウト]]までに非常に時間がかかり、
しかも[[利用者]]にはエラーの正確な原因が通知されず、
非常に悪い[[利用者体験]]となることがあります。
ネットワーク管理者は、安易にポートを制限して[[利用者]]を混乱させるべきではありません。

* 歴史

** 00年代の実装

[39] [TIME[2001年8月][2001-08]]に報告された[[フォーム]]を使った[[プロトコル横断攻撃]]に対処するため、
[[Mozilla]] は特定の[[特権ポート]]へのアクセスを遮断することにしました。
他の [[Webブラウザー]]も追随しました。

[REFS[
- [38] [CITE[Vulnerability Note VU#476267 - Standard HTML form implementation allows access to IMAP, SMTP, NNTP, POP3, and other services via crafted HTML page]] ([TIME[2016-03-11 21:16:52 +09:00]] 版) <http://www.kb.cert.org/vuls/id/476267>
- [1] [CITE[Mozilla Port Blocking]]
([TIME[2009-06-17 19:41:15 +09:00]] 版)
<http://www.mozilla.org/projects/netlib/PortBanning.html>
- [5] [CITE@en[Safari blocks content on some non-standard ports - Apple Support]] ([TIME[2015-03-31 15:02:33 +09:00]] 版) <https://support.apple.com/en-il/HT203772>
- [9] [CITE@en[Paper: HTML Form Protocol Attack]]
([[Jochen Topf]] 著, [TIME[2014-08-30 04:49:30 +09:00]] 版)
<http://www.remote.org/jochen/sec/hfpa/index.html>

[FIG(quote)[
[FIGCAPTION[
[8] [CITE@en[HTTP/HTTPS Port-Blocking in WinINET - IEInternals - Site Home - MSDN Blogs]]
([TIME[2015-03-31 16:25:26 +09:00]] 版)
<http://blogs.msdn.com/b/ieinternals/archive/2009/06/17/9769913.aspx>
]FIGCAPTION]

> IE8's current port-block list contains:
>  
>     19 (chargen), 21 (ftp), 25 (smtp), 110 (pop3), 119 (nntp), 143 (imap2), 220 (imap3), 993 (secure imap)
>  
> Blocking ports 220 and 993 is new to IE8. 

]FIG]

- [10] [CITE[Part2 - browsersec - Browser Security Handbook, part 2 - Browser Security Handbook - Google Project Hosting]]
([TIME[2015-03-31 16:41:34 +09:00]] 版)
<https://code.google.com/p/browsersec/wiki/Part2#Port_access_restrictions>
]REFS]

[15] [[IRC]] の 6667 番は [[Chrome]] や [[Firefox]] ではブロックされますが、
[[IE]] ではされません。 [[IRC]] サーバーの実装によっては、
[CODE[GET]] や [CODE[HEAD]] や [CODE[POST]] のような[[命令]] (大文字や小文字)
に対して
[PRE[
ERROR :"Oops, HTTP request received? This is IRC!"
]PRE]
... のように返答して接続を閉じるようです。

;; 命令として実装されているようなので、[[接続]]の先頭でなくてもそう動作します。

** WebSocket

[40] [[HTML5]] により規定される [[WebSocket]] は、
[[プロトコル横断攻撃]]を防ぐため、 [[port blocking]] を適用することを明文化しました。
ただしどの[[ポート]]を遮断するべきかは実装に委ねていました。

[REFS[
- [2] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2015-05-06 10:42:35 +09:00]] 版) <https://html.spec.whatwg.org/#dom-websocket>
]REFS]

[FIG(quote)[
[FIGCAPTION[
[7] [CITE@en-GB-x-hixie[HTML Standard]]
([TIME[2015-03-15 01:40:28 +09:00]] 版)
<https://html.spec.whatwg.org/#dom-websocket>
]FIGCAPTION]

> If port is a port to which the user agent is configured to block access, then throw a SecurityError exception and abort these steps. (User agents typically block access to well-known ports like SMTP.)
> Access to ports 80 and 443 should not be blocked, including the unlikely cases when secure is false but port is 443 or secure is true but port is 80.

]FIG]

[3] [[利用者エージェント]]が接続しないように設定されている[[ポート]]が指定されたら、
[CODE(DOMe)@en[[[SecurityError]]]] [[例外]]を投げなければ[['''なりません''']] [SRC[>>2]]。

[4] ただし [CODE(HTTP)[[[80]]]] と [CODE(HTTP)[[[443]]]] は、
制限する[['''べきではありません''']] [SRC[>>2]]。

;; [6] [CODE(HTTP)[[[80]]]] への [CODE(URI)@en[[[wss:]]]] や
[CODE(HTTP)[[[443]]]] への [CODE(URI)@en[[[ws:]]]] であっても、
制限するべきではありません [SRC[>>2]]。

[14] [[WebSocket handshake]] は異なるプロトコルを偽装して接続する攻撃を防ぐように設計されていますから、
他のプロトコルが動作するポートに接続できたとしても [[HTTP]] ほど問題にはならないかもしれません。

** Fetch

[18] 2016年3月に、 [[Fetch Standard]] で [[port blocking]] が規定されました。
[[HTML Standard]] の [[WebSocket]] に関する規定もこれに統合されました。
これによって誕生から15年を経て初めて[[Webプラットフォーム]]全体の [[port blocking]]
が明文化されました。

[REFS[
- [19] [CITE@en[Define port blocking · whatwg/fetch@eb07418]] ([TIME[2016-03-11 20:41:05 +09:00]] 版) <https://github.com/whatwg/fetch/commit/eb07418c8383983a9887498e49a2e2e986d3c9f4>
- [20] [CITE@en[Editorial: normalize port services · whatwg/fetch@11cdd86]] ([TIME[2016-03-11 20:41:19 +09:00]] 版) <https://github.com/whatwg/fetch/commit/11cdd86d2754c76b9eb7b23a96f1f15cbe613646>
- [21] [CITE@en[Editorial: one last nit around port blocking · whatwg/fetch@fc89332]] ([TIME[2016-03-11 20:41:35 +09:00]] 版) <https://github.com/whatwg/fetch/commit/fc893322dcab3e01b82fd6af3488bcf8765946fd>
- [22] [CITE@en[Update WebSocket to use Fetch's WebSocket alterations · whatwg/html@3dadbca]] ([TIME[2016-03-11 20:41:51 +09:00]] 版) <https://github.com/whatwg/html/commit/3dadbcad063a10b586ef52dd4b427aa339048ee7>
]REFS]

[41] [CITE@en[WebSocket: leave port blocking to the network layer (Fetch) · whatwg/html@17336ad]]
([TIME[2016-03-23 21:17:32 +09:00]] 版)
<https://github.com/whatwg/html/commit/17336ad69be4744dfc17194f2ee51bd730ca4d93>

[42] [CITE@en[Update WebSocket to use Fetch's WebSocket alterations · whatwg/html@3dadbca]]
([TIME[2016-03-28 23:10:44 +09:00]] 版)
<https://github.com/whatwg/html/commit/3dadbcad063a10b586ef52dd4b427aa339048ee7>

[44] [CITE[eduroam JP - Minimal available services (protocols)]]
([TIME[2009-10-06 06:07:16 +09:00]] 版)
<http://www.eduroam.jp/docs/thru-proto.html>

[50] [CITE@en[Editorial: use network and HTTP(S) scheme concepts]]
( ([[annevk]]著, [TIME[2016-05-30 21:46:40 +09:00]]))
<https://github.com/whatwg/fetch/commit/a7e7af28629938544d1b705225d04776261a2ff4>

[51] [CITE@en[Block more ports (427, 548, 6697)]]
([[annevk]]著, [TIME[2018-05-31 18:57:48 +09:00]])
<https://github.com/whatwg/fetch/commit/2e456740b0ce4145ef2a84bcc3bb5fa2e8b1f5b5>

[52] [CITE@en[Add { 548, 'afp' } to the blocked bad ports · Issue #694 · whatwg/fetch]]
([TIME[2018-06-05 18:36:38 +09:00]])
<https://github.com/whatwg/fetch/issues/694>

[53] [CITE@en[Block AFP ports (427, 548) by annevk · Pull Request #738 · whatwg/fetch]]
([TIME[2018-06-05 18:38:07 +09:00]])
<https://github.com/whatwg/fetch/pull/738>

[54] [CITE@en[Add several ports to the "bad ports" list. · Issue #482 · whatwg/fetch]]
([TIME[2018-06-05 18:39:40 +09:00]])
<https://github.com/whatwg/fetch/issues/482>

[55] [CITE@en[Fetch: port blocking change (427, 548) by annevk · Pull Request #11249 · web-platform-tests/wpt]]
([TIME[2018-06-05 18:41:06 +09:00]])
<https://github.com/web-platform-tests/wpt/pull/11249>

[56] [CITE@en[Centralize blocked port list · Issue #11346 · web-platform-tests/wpt]]
([TIME[2018-06-05 18:41:30 +09:00]])
<https://github.com/web-platform-tests/wpt/issues/11346>

[57] [CITE[Intent to Deprecate and Remove: Support for HTTP over port 9100, 6697, and 631. - Google グループ]]
([TIME[2018-06-05 18:43:23 +09:00]])
<https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/Ttkgd4aPkW0/7Uwd-S16BwAJ>