微信支付-Https与代理

支付-Https与代理

http proxy

tcp proxy

apache/nginx

squid

简单与交互,客户端证书

支付支持的TLS版本

支付的证书与有效期

信任链,CA

域名与证书

测试网络设置

简单

交互

SSL/TLS,HTTPS

代理设置

一个到某网站的HTTPS连接可被信任,当且仅当:

用户相信他们的浏览器正确实现了HTTPS且安装了正确的证书颁发机构;

用户相信证书颁发机构仅信任合法的网站;

被访问的网站提供了一个有效的证书,意即,它是由一个被信任的证书颁发机构签发的(大部分浏览器会对无效的证书发出警告);

该证书正确地验证了被访问的网站(如,访问时收到了给example.com而不是其它组织的证书);

或者互联网上相关的节点是值得信任的,或者用户相信本协议的加密层(TLS或SSL)不能被窃听者破坏。

SSL/TLS,HTTPS

WIKI: 传输层安全协议(傳輸層安全協議)

WIKI: 超文本传输安全协议(超文本传输安全协议)

简单与交互,客户端证书

简单

简单策略即传输只使用服务端证书+协商加密。一般来说,只要网络请求库支持TLS,就可以自动实现这个功能。

支付中除了资金敏感的接口以外,大部分都是这个策略。

具体请看接口说明中,关于是否需要证书的地方。

交互

参考示意图(傳輸層安全協議#/media/File:SSL_handshake_with_two_way_authentication_with_certificates.svg)

交互策略,也叫双向证书。除了使用服务器证书,客户端也必须使用特定的证书,才能和服务器交换秘钥,完成握手。

支付中,退款,发红包,企业付款,撤销等接口,使用的是这个策略。

具体请看接口说明中,关于是否需要证书的地方。

支付支持的TLS版本

参见公众平台公告(?action=getannouncement&key=&version=11&lang=zh_CN)

支付要求TLSv1.0及以上的版本。

(公众平台和开放平台也是一样的版本要求)

支付的证书与有效期

参见: 支付安全规范(?chapter=4_3)

信任链,CA

HTTPS的安全性,还涉及一个归纳问题:

只要公钥能解密,那么信息就是安全的

即逆推还要满足:

公钥必须是安全的

要证明公钥是安全的,使用的是背书的方式,即由另一个证书来保证这个证书的有效性。

那么最基础的那个证书就叫根证书。

一般来说,根证书是跟着ssl库一起分发的。更新ssl库就可以获得最新可信任的根证书。

在没有办法更新的情况下,支付的证书的根证书,也打包在压缩包里,可以选择导入(即手动信任根证书)。

域名与证书

证书和域名是强相关的。

这是由于互联网请求会有钓鱼问题。也就是公钥是安全的,加密也是安全的,但是请求目标却是假的。

https库在连接目标的时候,会验证目标的证书和本地请求的域名是否一致。

所以使用https请求的时候,是无法使用ip地址请求目标的。

解决这个问题的方法一般是在hosts当中给这个ip绑定一个域名。或者设置本地请求的时候不要验证此项。

测试网络设置

curl -k -d "@add_merchant.txt" --key "apiclient_key.pem" --cert "apiclient_cert.pem" ?action=add

代理设置

为https请求设置代理非常复杂,主要是由于代理本身相当于是中间人的角色。

代理本身是分层的,通常的代理叫http代理,是在http协议层进行代理和转发。也就是说像这样:

client<--http(s)--> proxy <--http(s)--> server

对于简单策略的https,这样做问题不大,因为对服务器而言,代理就相当于客户端,实际客户端不可见。而代理和实际客户端之间可以选择http请求,这样虽然客户端想请求服务器,实际请求的却是代理,不会发生域名不一致的错误。

但是对于交互策略的https就会产生问题:实际报文到服务器的时候,必须已经被加密。但是如果是实际客户端加密,proxy就无法工作。所以客户端的证书只能部署在代理上,缺点会很明显:

证书安全多了个地方需要维护,而且暴露在外网。

如果涉及多个客户端证书(支付内即涉及多个商户号),代理上需要复杂的切换方案,比如多个代理地址。

这个时候有个比较少见的代理可以解决这个问题,即tcp代理。也就是tcp端口转发,还有地方会叫反向代理。

tcp代理不需要关注http包内容,不存在拆包。所以ssl加密可以由客户端完成。也就解决了上面的两个缺点:

证书放在实际客户端。

客户端代码即可以控制证书切换。

但是tcp代理确实相关文档较少,尤其是关于高性能要求环境下如何动态伸缩的指导较少。

http proxy

apache/nginx

nginx的proxy文档:ngx_http_proxy_module()

squid

ssl bump()

tcp proxy

我实现的支付专用tcp proxy,相当于是个demo: https://github.com/btbxbob/wxpay-reverse-proxy

nginx的tcp proxy扩展,注意需要重新编译nginx: