在杭州飘雪前结束的高校网络信息安全从业人员网友见面会上,中国科学技术大学张焕杰介绍了《校园网站安全防护之Nginx》,张大神活生生把Nginx从一个高性能的Web容器玩成了一个安全设备。因为我最近也在学张大神玩Nginx,所以顺着张大神的PPT说开来。在阅读之前,最好你可以先阅读完张大神的PPT和视频资料,里面对Nginx如何在中国科学技术大学的应用已经说得非常清楚了。

下面我会直接把Nginx的使用说成应用交付,虽然应用交付的概念比Nginx广更多。

为什么必须有应用交付

首先说为什么每个学校都应当有一个Nginx或者商业的应用交付设备。

在很多学校的信息与网络中心内,网络管理员追求的是稳定,负责Web安全的人为了分析等用途想要在主干串入一个设备是有一定难度的。Web流量和其他TCP流量混在一起,虽然Web流量是无状态的,割接的时候丢几个包说实话也不会有太大的问题,然而TCP有些数据库连接、备份应用连接、心跳连接是长期的,丢几个包会造成什么后果因为不懂也没人敢打包票。而且在所有包里串入一个只为Web使用的设备,对这台设备的性能要求提高了几个数量级,也会导致每次任何故障排查都要考虑到这台设备,无法做到很好的隔离。所以分离Web流量是必须的。当然你可以用类似什么SDN、策略路由、服务链(网络这里我不懂)等等技术将Web流量引流到某些地方,这些要看你目前网络的架构。

就算你可以做好Web流量分离,然而接下来还会遇到HTTPS问题。如果你不考虑全校HTTPS那可以忽略。HTTPS证书一个一年439-2191.3元不等,如果是一千个站点,一年成本在44万左右。一个通配符域名1999-5673.3元不等,HTTPS证书私钥的泄露会造成中间人攻击,所以也是不能申请一个发给所有子网站来使用的。

当然也有免费的方案,Let’s Encrypt,3个月更新一次,可以完全自动化,对每个网站管理员的技术水平有一定要求。而且如果你要监管,你必须要求这些管理员申请到证书后提交给你才能对其进行WAF防护。如果要动到DNS Challenge Validation的话,网站管理员又没有DNS的控制权,DNS服务器也不会开放API给管理员来调用。所以怎么看都必须由校方统一申请了。然而Let’s Encrypt申请有限制,一个注册域名下的子域名一个星期只能50个,每个证书可以折叠100个域名,也就是张大神的做法,通过很精巧的控制,在3个月周期内每天轮流renew不同的证书,如果能用满配额,实际上可以申请到6万个免费的网站HTTPS证书,然而证书的折叠需要证书拥有者主体最好是同一个人。我原先也考虑过这个问题,我在备案系统内使用DNS Challenge为每个域名申请免费的Let’s Encrypt证书,因为备案系统有管理员的信息,所以可以以每个管理员负责的域名或者同一个服务器IP来做折叠,然后让管理员可以手动或者自动wget下载,让WAF定期更新对应域名的SSL证书,这样子申请的免费域名在rate limits内,我又有所有的私钥,管理员使用成本也很低。

然而折叠的证书也会泄露域名信息。泄露域名其实也不是很大的事情,DNS爆破的工具多了。这么折腾,不如直接在前端拦截一个Nginx或应用交付来解决。

而且应用交付有个最大的安全好处就是他可以对外隐藏你的服务器,任凭你内部如何波涛汹涌,最终可以交付出一个清晰的网站地图。

Nginx能带来的好处

  • 更简单的Web流量分析

    只有单纯的Web流量,数据包减少了几个数量级。

  • 日志统一统计

    强制性的全校Web服务器访问日志留存。原先需要各个Web服务器扔日志到共同的日志中心,配置和部署很麻烦。而且这个日志是真实访问的日志,是非常有价值的日志,对于校内各个网站的结构和信息系统指纹分析是个非常有用的源头。

  • WAF

    由于进行了DNS引流,即使学院的服务器不在数据中心,也可以通过WAF,而且类似张大神,WAF放在HTTPS后面,WAF的配置也很简单。

  • IPv6
  • HTTP2

    大神说到支持HTTP2、HTTP3,我原先以为只是个比喻,是个泛指,确实HTTP3已经在计划了,HTTP2使用了二进制,HTTP3将会使用UDP。在我日志的观察中,HTTP2的流量已经较高了,客户端支持比较普遍了,只不过服务器原先不支持而已。下面是几小时内60万的访问日志统计,如果去掉HTTP/1.1的跳转HTTP2占比会更高。

  • HTTPS

    统一的位置进行SSL卸载,可以用硬件或者软件加速。还有前面提到的,节省经费,增加私钥的安全性。

  • 全校所有Web的多出口

  • 对外只有几个IP

    相当于做了个Web的NAT,把内部提供Web服务的服务器都隐藏起来。原先教育网很多学校很壕,IP很多(这也是应用交付在高校内用的不多的一个原因),都是服务器分配公网IP直接对外提供服务,管理上简单粗暴。如果用了应用交付,真实服务器只允许应用交付访问Web端口,就稍微安全一点了。

  • 认证

    可以在上面基于IP的认证,统一身份认证的认证。通过了认证,才转发,否则给提示信息,很友好。有点类似部分WebVPN的功能,只要DNS指过来的网站,都可以实现VPN访问的效果。在张大神的设计当中,为了简单和轻量,使用了无状态的设计,通过将密码+nginx_auth_uid+nginx_auth_expire hash后的nginx_auth_hash写入客户端,每次根据这些字段重新计算,这会遇到有效期选择长度和如何续期的问题,如果是一个固定的有效期长度,那必然用户会遇到连续访问过程当中有可能在过期后需要再次登录的问题,如果过期时间在某次访问中间,是否有可能造成页面部分元素通过认证而部分没有通过造成的奇怪的错误信息呢?因为我还没玩到,所以不是太了解,如果使用有状态的设计,通过将Session ID写入Cookie,后端通过memcached来访问,同时自动续期,不知道对性能影响有多少。

  • 一键断网

    一键断网的成本可以非常低

  • 基于HTTP Header的加固

    比如X-Frame-Options,server token,CSP,Referrer Policy。。。

Nginx带来的问题

应用交付是一定要上的,但是上的过程由于后端应用需要一些小调整,所以需要拉长实施的时间,成熟一个上一个。而且你可能需要多个应用交付隔离,有些应用无法上应用交付或者建议不上。

  • 鸡蛋都在一个篮子里了

    由于所有的DNS都指向应用交付,所以如果应用交付服务器故障或被DDoS,影响范围会比较广。这里会涉及到单点故障点增加,原先是鸡蛋(服务器)在很多篮子(IP和交换机)里,现在是鸡蛋都在一个篮子(应用交付)里了,当然不管如何,篮子他们都永远在一辆狂奔在信息高速公路上的车(核心交换机)里。对于自己做的Nginx,最好做高可用,至少2台起步,还可以滚动升级。

  • 真实IP问题

    由于通过了应用交付,所以后端真实服务器看到的都是应用交付的IP,真实服务器必须做些调整。应用交付使用的日志服务器应当非常健壮,监管要求的6个月日志保存的客户端IP只有应用交付有。

  • 页面HTTPS和HTTP混用

    用了HTTPS,由于浏览器只有一个位置显示HTTPS证书,所以浏览器希望嵌入的内容也必须是HTTPS的,而且等级比显示得更高,所以如果网页内嵌入的资源还是写死HTTP的必须修改,要不也升级到HTTPS,要不不嵌入。写死的链接可以使用类似去掉http:和https:的 //dog.xmu.edu.cn 来做协议的自适应。

  • DNS和IP对应数据迁移

    原先DNS权威服务器负载了大部分的域名和对应关系,通过引入应用交付,这些数据迁移到应用交付了,所以你的漏洞扫描、资产发现等等服务器通过域名来找IP就不准确了,需要去获取应用交付的数据。如果原先应用为了应对域名和IP对应关系的变更使用域名来连接,就必须变成写死IP或者使用hosts或者自建DNS来处理。

  • 非Web服务无法代理

    理论上也是可以代理的,只不过复杂度加大了,所以类似视频或者邮件有MX、POP3、SMTP、IMAP没有做好和Web分离的不能被代理。有些选课等应用,或者网盘等应用,应当考虑也做分离,不在同一个应用交付上。

  • 纯IP没有域名或非标准端口的网站

    清理,使用二级目录会增加配置复杂度,查错也会更麻烦。

  • 真实服务器不要IPv6、HTTPS、HTTP2、强制跳转

    这些让应用交付做,不要干扰应用交付的工作,比如HTTP到HTTPS的强制跳转如果开了,客户端浏览器访问应用交付HTTP,被跳到HTTPS,应用交付访问真实服务器是HTTP,就会导致跳转死循环。重要应用或者测试过程中可以配置rewrite规则,对应用交付IP不启用自动跳转。

  • 旧有应用无法自动跳转

    浏览器有自动跳转机制,然而很多使用代码去获取的应用无法自动跳转,比如我们去获取CAS的API端点、某个应用去访问某个新闻RSS链接等等,都必须修改。

  • 五级域名HTTPS问题

    五级域名在学校内相当于三级域名,类似 www.dog.xmu.edu.cn ,这种如果多了的话,HTTPS需要多申请。应用交付配置也会复杂。建议开始清理五级域名。

  • 负载均衡和缓存

    由于做了拦截,也可以做热点数据缓存,HTML内容缓存固定时长,可以大大降低后端应用的压力,然而后端应用必须输出缓存时间,如果没有,也可以在应用交付强制缓存,但是要注意缓存Key的选择,不要出现用户之间串页面的安全问题。当然也可以做负载均衡,是否单纯转发让应用自己去做负载均衡还是在应用交付做需要衡量,我的建议是保持单纯。

  • Nginx的优化

    张大神提到了conntrack、server_names_hash_bucket_size、ulimit的优化。

我打算怎么做

我现在还没怎么做,这里涉及到选择开源软件和商业软件的问题,有机会以后说。

我喜欢自动化部署和堆砌开源软件,所以自己做的话,我会2台Nginx,使用一个虚IP,使用KeepAlived做高可用。CPU、内存、网络、stub_status等日志使用collectd收集,写到Prometheus,使用Grafana展示大屏。

accesslog和errorlog一份扔到远程syslogd,在Elasticsearch+Kibana或者Splunk展示大屏,一份扔给Hadoop类的以日期为文件名的文本文件内保存以备未来分析。中间可以再加入基于Docker、Flask、LDAP认证和OTP双因素认证。有机会的话开源自动化部署代码。

参考文档

  • https://ipv6.ustc.edu.cn
  • https://github.com/bg6cq/nginx-install
  • https://github.com/bg6cq/nginxauth
  • 5分钟让你的老旧网站支持IPv6、HTTPS、HTTP/2,不能再多了
  • 继续说IPv6、HTTPS、HTTP/2,系列完结吧