saber 酱的抱枕

Fly me to the moon

03/8
2023
软件

IIS 7.5 无法绑定多个 HTTPS 站点,以及用 Nginx 解决此问题的记录

来自低版本 IIS 受害者的记录,愿你不会用到过时的软件。

最近我维护的几个网站需要启用 HTTPS,这些网站有多个不同的主域名,部署在 Windows Server 2008 SP 1 的 IIS 7.5 上面。

IIS 7.5 无法绑定多个 HTTPS 站点,以及用 Nginx 解决此问题的记录

之前我刚在一台 IIS 10 的服务器上为一些网站添加了 HTTPS,但是这次却遇到问题了,因为 IIS 7.5 版本太低了。

在 IIS 10 上面添加新的绑定时,选择 https 协议,界面是这样的:

IIS 7.5 无法绑定多个 HTTPS 站点,以及用 Nginx 解决此问题的记录

然而在 IIS 7.5 上,界面是这样的:

IIS 7.5 无法绑定多个 HTTPS 站点,以及用 Nginx 解决此问题的记录

红框里是两者的 2 个区别:

  1. IIS 7.5 不能输入主机名
  2. IIS 7.5 没有“服务器名称指定”功能

IIS 7.5 缺失的这两个功能导致了两个问题。

第一个问题就是不能输入主机名,这姑且可以解决,打开 C:\Windows\system32\inetsrv\config\applicationHost.config,找到要添加 https 绑定的站点,之前已经有 http 绑定了,现在在下面添加 https 的绑定。例如:

<site name="站点名" id="1" serverAutoStart="true">
    <application path="/" applicationPool="站点名">
        <virtualDirectory path="/" physicalPath="E:\web1" />
    </application>
    <bindings>
        <binding protocol="http" bindingInformation="*:80:www.a.com" />
        <binding protocol="http" bindingInformation="*:80:www.b.com" />
        <binding protocol="https" bindingInformation="*:443:www.a.com" />
        <binding protocol="https" bindingInformation="*:443:www.b.com" />
    </bindings>
</site>

但是此时这些 https 绑定并没有对应到它们自己的证书,这就会引出第二个问题。

在 IIS 里编辑绑定,选择这个 https 绑定所对应的证书,就会因为没有“服务器名称指定”功能而看到提示:

IIS 7.5 无法绑定多个 HTTPS 站点,以及用 Nginx 解决此问题的记录

IIS 7.5 无法绑定多个 HTTPS 站点,以及用 Nginx 解决此问题的记录

“服务器名称指定”就是 SNI 功能,如果网站服务器没有 SNI,那么一台服务器(即 1 个 IP)上面只能绑定 1 个 HTTPS 站点。如果你添加了第二个 HTTPS 绑定,第一个就会失效,总之这个服务器只支持一个 HTTPS 解析。

这个问题我搜索了一大圈,没找到可行的解决办法。


关于 SNI 什么是可以看这里:https://www.globalsign.com/en/blog/what-is-server-name-indication

对于 IIS 8 或更高版本,在添加 https 绑定时可以启用“服务器名称指定”,或者在 applicationHost.config 里面设置 sslFlags1 启用 SNI。例如:

<binding protocol="https" bindingInformation="*:443:www.a.com" sslFlags="1" />
<binding protocol="https" bindingInformation="*:443:www.b.com" sslFlags="1" />

但是发布于 2009 年的 IIS 7.5 并不支持 sslFlags 标记,添加这个标记会导致 IIS 报错。(相关文档:https://learn.microsoft.com/en-us/iis/configuration/system.applicationHost/sites/site/bindings/binding


为了解决 IIS 7.5 无法绑定多个 HTTPS 站点的问题,我尝试在这台服务器上使用 Nginx,让 IIS 负责 HTTP 网站,Nginx 负责 HTTPS 网站。

我先在 IIS 中删除了 HTTPS 绑定,重启 IIS 服务。

然后下载 Nginx 的 Windows 安装包并解压出来:http://nginx.org/en/download.html

接下来修改 Nginx 的配置文件 conf/nginx.conf,把默认站点监听的 80 端口改为 443。

listen       443;

这是因为 IIS 和 Nginx 默认都会监听 80 端口,端口冲突时 Nginx 启动不了。在 logs/error.log 里会输出错误信息:

bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket in a way forbidden by its access permissions)

修改端口后,执行命令 start nginx.exe 启动 Nginx。

如果在任务管理器里看到有 2 个 nginx.exe 的进程就表示启动成功了。此时在 IE 浏览器里访问 http://127.0.0.1:443/ 能够看到 Nginx 的欢迎页面,在外网通过 http://{IP}:443/ 也可以正常访问。

IIS 7.5 无法绑定多个 HTTPS 站点,以及用 Nginx 解决此问题的记录


但是 Nginx 在 Windows 上不会作为服务运行,这意味着当前登录用户注销后,nginx.exe 也会结束运行。

搜索“如何把 Nginx 作为服务运行”,可以看到有很多种方法,有些比较早的方法不仅操作复杂,还有一些缺陷。仔细对比之后我根据 Stackoverflow 上的一个回答,使用一个叫 NSSM 的软件把 Nginx 包装成了服务。(来源:https://stackoverflow.com/a/41467168

IIS 7.5 无法绑定多个 HTTPS 站点,以及用 Nginx 解决此问题的记录

(如果 Nginx 已经在运行,则需要先退出它,然后再把它安装为服务,避免重复运行)

通过 NSSM 操作之后,可以在服务里看到 nginx 服务:

IIS 7.5 无法绑定多个 HTTPS 站点,以及用 Nginx 解决此问题的记录

此时启动服务即可,注销后再次登录可以看到 Nginx 依然在运行,默认网站也可以照常打开。

修改了 Nginx 的配置文件之后,可以重启动此服务来达到重载 Nginx 的目的。

如果想要通过执行命令 nginx -s reload 来重载 Nginx,则需要修改服务的运行用户:

查看服务的属性,“登录”选项卡里默认是“本地系统账户”,将其改为当前登录的用户 Administrator。

IIS 7.5 无法绑定多个 HTTPS 站点,以及用 Nginx 解决此问题的记录

因为我们用 CMD 执行命令 nginx -s reload 时不是系统账户,如果服务是以本地账户运行的话,因为用户身份不一致就会导致命令执行失败。

把登录用户修改为 Administrator 不会影响服务的运行效果,用户注销后 nginx.exe 进程依然存在。


之后修改 Nginx 的配置文件 conf/nginx.conf,把默认网站的 server 节点删除,然后启用 HTTPS server 下被注释掉的 server 节点,填入网站信息,如:

server {
 listen       443 ssl;
 server_name  www.a.com;

 ssl_certificate      E:/cert/nginx/xxx_www.a.com.pem;
 ssl_certificate_key  E:/cert/nginx/xxx_www.a.com.key;

 ssl_session_cache    shared:SSL:1m;
 ssl_session_timeout  5m;

 ssl_ciphers  HIGH:!aNULL:!MD5;
 ssl_prefer_server_ciphers  on;

 location / {
     root   E:/web1;
     index  index.html index.htm;
 }
}

由于这台服务器是 Windows 系统,复制的文件路径里分隔符是反斜线 \,需要修改成 Unix 风格的 /

之后重载 Nginx,在外部浏览器里用 https 协议访问网站,可以正常打开。

接下来把需要用 https 访问的其他网站也依次配置,复制粘贴再修改一下就搞定了。


最后需要做个访问 http 自动跳转到 https 的 URL 重定向。

这台服务器比较特殊,之前的 http 站点都在 IIS 上,需要在 IIS 里设置跳转,但是 IIS 里没有 https 站点。

我本以为这不能跳转到 Nginx 里的 https 站点,但是当我用 IIS 的 URL 重写模块设置了重定向之后,出乎意料的正常打开了 https 站点,并且证书也是正确的。

可能是 IIS 重定向到 https 网址时并不是在自己内部寻找对应的 HTTPS 绑定,而是把请求转发到了 443 端口,这样才能被 Nginx 正确接管吧。这太好了,如果 IIS 做不到这样的话,我就得把这些 http 网站转移到 Nginx 里,然而由于 80 端口冲突,事情会变成需要我把 IIS 里的所有网站都转移到 Nginx 里,然后停用 IIS。这下省事多了。

IIS 7.5 无法绑定多个 HTTPS 站点,以及用 Nginx 解决此问题的记录