解决钉钉服务器出口IP不确定问题:自签名根证书+hosts文件+nginx反向代理

问题来源

企业内部应用一般部署在内网,没有固定的公网IP,这样在访问钉钉的API时就会被拦截下来。钉钉的服务器出口IP只支持一个统配符,出现不匹配的情况就会被拦截。

解决方案比较

当然存在多种解决方案,各有差别,但是本质都需要一个公网服务器,公网搭设一个代理服务:

  1. 在代码中使用代理。对代码具有一定的侵入性。
  2. 使用系统代理。这样需要用PAC来选择代理的网址,对一些程序可能无效。
  3. 使用iptables转发到代理软件。仅限于linux可用。

这里我介绍一种用反向代理的方法解决没有固定IP的方案。内网的windows服务器只需要一个根证书、改Hosts文件即可。

解决方案

先决条件

  1. 公网服务器且系统为Linux、固定的公网IP

步骤

  1. 生成自签名的根证书 + 域名证书
    OpenSSL 自签 CA 及 SSL 证书参考这篇文章即可。注意把域名改成oapi.dingtalk.com,将csr文件转换为pem文件。

  2. 在公网配置Nginx的反向代理,使用如下配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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;
}
}
  1. 在内网服务器,把根证书导入到受信任的根证书颁发机构

  2. 在内网服务器,设置Hosts文件

1
<公网ip>  oapi.dingtalk.com
  1. 重启nginx,即可在内网服务器上访问反代的钉钉API

简要分析原理

本地hosts文件强制解析到自有服务器上,中间的证书是自签名认证的,服务器获取到请求后转发给真正的钉钉服务器,这样出口IP就确定了下来,能过验证。注意根证书的私钥不要泄露了,否则带来中间人攻击的风险。

Author: whllhw
Link: https://whllhw.ml/posts/2019/12/28/解决钉钉服务器出口IP不确定问题:自签名根证书-host-nginx反向代理/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.