如何使用SNI获得自定义NSURLProtocol

问题描述 投票:0回答:1

首先是服务器端:有一个内部可达的apache服务器,有几个虚拟主机。对于http(sans的'!)请求,我使用IP作为URL并在Host-Headerfield中添加主机名。

这非常有效。

但是当我建立SSL连接时,我遇到的问题似乎与SNI有关。

我找到了这个Overriding TLS Chain Validation Correctly并在我的代码中实现了它。

所以我更新了信任

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)

但我仍然从服务器获得400。

更新:URLSession确实支持SNI但我的问题是我需要添加额外的或更改hostname中的SSLHandshake

首先是服务器的简短描述:服务器是一个Apache服务器,只能通过IP访问,但它有多个vhost,可以通过主机名在本地使用,但是当我从像iPhone这样的外部设备连接它们时,我必须在Host-Headerfield中添加vhost的主机名。

所以我做的是:我用一个基于IP的URL创建一个URLRequest,然后添加带有主机名的HOST Headerfield

if let url = URL("https://192.168.178.54:8890") {
    var request = URLRequest(url: url)
    request.addValue("foobar:8890", forHTTPHeaderField: "Host")
    …
}

这对于非安全的http请求是有效的,但是一旦使用https,服务器就会返回“400 Bad request”,http-ssl-error.log包含以下错误:

[Tue Jul 11 09:35:51 2017] [error] Hostname 192.168.178.54 provided via SNI and hostname foobar provided via HTTP are different

这是因为默认情况下,SSLHandshake使用URL中提供的值,在我的例子中,这是IP。

我现在试图弄清楚的是如何在SSLHandshake中提供不同的主机名,或者提供类似自己的DNS解析器的东西,我仍然可以使用基于主机名的URL,但iOS直接获得路由。

ios swift nsurlsession sni nsurlprotocol
1个回答
0
投票

首先我们如何解决它:服务器工作者最终完成了他们的工作,并没有搞乱botchy设置。

我还在Apple Dev Forums发布了我的问题

我也从我的TSI收到了这个:

将你的事件传递给我,因为我通常在DTS(我在你的事件最初进入时不在办公室)的NSURLSession和TLS问题上起带头作用。

回到您的技术问题,似乎我通过您为此创建的DevForums主题回复了您。

https://forums.developer.apple.com/thread/82179

这种反应相当简短,但确实涵盖了重点:

  • 无法在NSURLSession级别配置SNI名称
  • 我推荐的替代方案是使用.local DNS名称

如上所述,我的DevForums响应相当简短,所以如果你对后者有任何跟进问题,我很乐意在这里回答。

您/可以/覆盖网络堆栈中较低级别的SNI名称,即CFSocketStream(通过NSSStream和CFStream API访问)和安全传输。从理论上讲,您可以在NSURLProtocol子类中实现自己的HTTP协议层,使用这些API用于TLS-over-TCP方面,但我/强烈/建议不要这样,因为它是一项大量的工作。

分享和享受 - 奎因“爱斯基摩人!” Apple Developer Relations,开发人员技术支持,核心操作系统/硬件

© www.soinside.com 2019 - 2024. All rights reserved.