关于Private Network

2,469 阅读3分钟

现象

最近在我的Windows 11上升级Chrome浏览器版本到98版本之后,访问我们内部的开发网站时出现了大量的报错:

Access to XMLHttpRequest at 'https://***.test.com/jsonp' from origin 'web.test2.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Private-Network' header was present in the preflight response for this private network request targeting the private address space.

虽然是一个CORS的错误,但是上面的报错以前比较少见。翻译过来看,就是进行preflight请求的时候,返回的HTTP header 没有 Access-Control-Allow-Private-Network,问题是,Access-Control-Allow-Private-Network 是什么?

Access-Control-Allow-Private-Network

Google一下,发现chrome的支持文档中对于Access-Control-Allow-Private-Network有描述:

Chrome sends a CORS preflight request ahead of any private network requests for subresources, asking for explicit permission from the target server. This request carries a new Access-Control-Request-Private-Network: true header, and the response must carry a matching Access-Control-Allow-Private-Network: true header.
A private network request is any request from a public website to a private IP address or localhost, or from a private website, for example, an Intranet, to a localhost. Sending a preflight request mitigates the risk of cross-site request forgery attacks against private network devices such as routers, which are often not prepared to defend against this threat.
Chrome 98 sends these preflight requests but does not yet require them to succeed. Failed preflights only display warnings in DevTools, which you can use to detect problematic fetches in your web apps.  In Chrome 101 at the earliest, failed preflights will cause the entire request to fail depending on compatibility data. See the blog post for more information.

主要讲明白一个事情,当我们访问 private network时,Chrome 98版本会发送一个 CORS preflight 请求,这个请求头带了Access-Control-Request-Private-Network: true,要求服务器返回的HTTP Header时带上 Access-Control-Allow-Private-Network: true,如果没有返回,那么在Chrome 101版本之后会报错,并且抛出请求失败的错误,但是Chrome 98只是抛warning,不影响请求状态。

讲道理,我的Chrome 98不应该抛错误的,实际上,Windows 11的Chrome浏览器升级到98版本之后,就会因为Access-Control-Allow-Private-Network抛错误。 经过测试,在Windows 10和Mac上的Chrome 98都没有这个问题。

怎么解决问题?

既然知道问题出在哪里,那就很简单了,只需要在开发环境的Preflight Response中带上Access-Control-Allow-Private-Network: true就好。

作为一个热爱技术的好同学,我当然不满足于解决一个问题啦。于是阅读了一些文档,整理了一部分关于private-network的知识,与诸君共享。

1. 什么是 Private Network Request

Private Network Request其实是指访问的服务器的IP地址比较Private的请求,例如从一个Public的网站发出请求访问IP地址比较Private的网站内容(例如JSONP),又或者是从Private的网站访问localhost。

image.png

Relationship between public, private, local networks in Private Network Access (CORS-RFC1918) 上图蓝色部分就是属于Private Network Request,一定要记清楚哦

那什么样的IP地址算Private呢?有一份CORS-RFC1918的标准讲清楚了这个问题,大家可以去读一下。我摘录了一下重点:

10.0.0.0 - 10.255.255.255 (10/8 prefix)
172.16.0.0 - 172.31.255.255 (172.16/12 prefix)
192.168.0.0 - 192.168.255.255 (192.168/16 prefix)

所以,类似 192.168.31.1 这样的IP地址就算是Private了。

2. 如何成功访问Private Network?

Preflight Request Header带上:Access-Control-Request-Private-Network: true
Preflight Response 包含: Access-Control-Allow-Private-Network: true

例如:
Request:

HTTP/1.1 OPTIONS /cat.gif
Origin: https://foo.example
Access-Control-Request-Private-Network: true

Response:

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Private-Network: true

3. 什么情况下受影响?

  • 101版本以后的Chrome(可以看RoadMap
  • Windows 11的 98版本的Chrome, 我总感觉这是一个bug,但是还没有空找根本原因

关于Private Network的介绍就到这里了哈。后续有更多信息出来时再更新。