问题来源
企业内部应用一般部署在内网,没有固定的公网IP,这样在访问钉钉的API时就会被拦截下来。钉钉的服务器出口IP只支持一个统配符,出现不匹配的情况就会被拦截。
解决方案比较
当然存在多种解决方案,各有差别,但是本质都需要一个公网服务器,公网搭设一个代理服务:
- 在代码中使用代理。对代码具有一定的侵入性。
- 使用系统代理。这样需要用PAC来选择代理的网址,对一些程序可能无效。
- 使用iptables转发到代理软件。仅限于linux可用。
这里我介绍一种用反向代理的方法解决没有固定IP的方案。内网的windows服务器只需要一个根证书、改Hosts文件即可。
解决方案
先决条件
- 公网服务器且系统为Linux、固定的公网IP
步骤
生成自签名的根证书 + 域名证书
OpenSSL 自签 CA 及 SSL 证书参考这篇文章即可。注意把域名改成oapi.dingtalk.com
,将csr文件转换为pem文件。在公网配置Nginx的反向代理,使用如下配置文件
server {
# SSL configuration
listen 443 ssl;
listen [::]:443 ssl;
ssl on;
ssl_certificate /home/ubuntu/certs/oapi.dingtalk.com.pem; # 公钥路径
ssl_certificate_key /home/ubuntu/certs/oapi.dingtalk.com.key; # 私钥路径
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1 TLSv1.2;
ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
ssl_prefer_server_ciphers on;
server_name oapi.dingtalk.com;
location ~ / {
proxy_set_header Host $host;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://oapi.dingtalk.com;
}
}
-
在内网服务器,把根证书导入到受信任的根证书颁发机构
- 在内网服务器,设置Hosts文件
<公网ip> oapi.dingtalk.com
- 重启nginx,即可在内网服务器上访问反代的钉钉API
简要分析原理
本地hosts文件强制解析到自有服务器上,中间的证书是自签名认证的,服务器获取到请求后转发给真正的钉钉服务器,这样出口IP就确定了下来,能过验证。注意根证书的私钥不要泄露了,否则带来中间人攻击的风险。