Skip to content

Latest commit

 

History

History
274 lines (173 loc) · 12.5 KB

README.md

File metadata and controls

274 lines (173 loc) · 12.5 KB

如何搭建一个树洞

0 开始搭建树洞之前

如果你在看这篇文章,可能或多或少你对搭建树洞有着一定的兴趣。因此,首先需要强调的是:搭建并运营一个树洞是一个工作量巨大并且难度很高的事情。树洞的运营是一个一定需要一支团队才可以胜任的任务,并且这个团队至少需要有以下几点能力:

  • 技术:搭建树洞、树洞功能更新时都需要技术能力
  • 网络安全:树洞的隐私保护是重中之重,也是树洞用户非常关心的问题
  • 日常管理:团队中最好需要管理员7/24值班管理树洞,管理员还需要有极高的舆情处理能力,同时看得懂各种黑话
  • 法务:日常管理中遇到的各种问题都可能需要法务帮忙

在你想要开始搭建树洞之前,请确保你身边有一群你们相互信任的伙伴,你们的合力可以覆盖上面几点能力

1 对技术人员的要求

树洞的技术栈目前已经较为复杂,后端使用的是Linux+Nginx+MySQL+Redis+Go;Web前端使用的是React;Android前端主要是Kotlin;iOS前端是SwiftUI。如果要完成树洞后端的搭建,技术人员至少需要掌握:

如果你掌握了这些基础,那么请继续往下看吧!搭建树洞至少需要1天的时间,请保持耐心。

2 选择一个云服务器提供商和操作系统

树洞的后端需要运行在一个有公网IP的服务器中,至少需要1核2G内存,最好2核4G内存或以上。市面上现在有很多服务器提供商,国外大厂商有Amazon AWS、Google Cloud、Microsoft Azure等,小厂商有Digitalocean、Vultr、Linode等,国内知名的有阿里云、腾讯云、华为云等。它们之间的对比如下表:

备案 价格 网络速度
国外大厂商 不需要 比较贵 晚上国际出口可能很慢
国外小厂商 不需要 比较便宜 晚上国际出口可能很慢
国内厂商 需要 很贵

选择完厂商之后,就选择一个操作系统吧,对于服务器来说,操作系统最重要的特性就是稳定。因此,我们推荐CentOS 7,它的官方支持将在2024年6月才结束。

3 注册一个域名

注册域名实在是太简单了,网上的教程很多。这里需要强调一下安全问题

【⚠必须采取的安全措施】:请务必确保时刻没有子域名DNS解析到服务器真实IP,并且服务器真实IP必须始终保密!

服务器的IP如果泄露,DDoS等情况就有可能发生,同时还会极大地增加攻击面。因此,服务器的HTTP流量必须始终通过CDN(比如Cloudflare CDN)。在https://securitytrails.com/dns-trails 网站上,一个域名的全部子域名和DNS历史记录都可以轻松查到,因此不能有任何时刻让服务器真实IP暴露在外。

【建议的安全措施】:请使用堡垒机登录ssh

堡垒机可以减少一定的攻击面,对服务器安全是很有益的。如果树洞运营团队有条件,请使用堡垒机。

4 在服务器上搭建后端

第一步:设置时区为Asia/Shanghai

sudo timedatectl set-timezone Asia/Shanghai

请相信,这会节省很多麻烦的

第二步(可选):安装swap空间

有swap空间可以让服务器在内存吃紧的时候有着更好的表现。如果你的服务器硬盘是SSD的,那么swap会消耗SSD寿命;不过如果你是租的服务器,谁会在意寿命呢:)

参考教程:https://www.digitalocean.com/community/tutorials/how-to-add-swap-on-centos-7

第三步:安装并配置Nginx,同时配置firewalld或iptables防火墙

参考教程:https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-centos-7

【⚠必须采取的安全措施】:请务必配置好iptables或firewalld或使用服务器提供商的安全组功能,仅允许CDN流量访问80/443端口

否则,攻击者可以通过全网扫描的方式获取服务器的真实IP,参考:https://cloud.tencent.com/developer/article/1079482

如果你使用的是基于iptables的防火墙,那么我们在此提供一个示例脚本,你可以使用以下脚本方便地添加Cloudflare的节点进入iptables白名单:

#!/bin/bash
iptables -F
ipset destroy cf4
ipset create cf4 hash:net
for x in $(curl https://www.cloudflare.com/ips-v4); do ipset add cf4 $x; done

iptables -A INPUT -m set --match-set cf4 src -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j DROP
iptables-save

这个脚本要求ipset已经被安装。如果你看不懂这段脚本在干什么,请先搜索学习相关知识之后,再进行后续步骤。

第四步:安装并配置MySQL 8.0,Redis,Go

参考教程:

https://www.mysqltutorial.org/install-mysql-centos/

https://www.digitalocean.com/community/tutorials/how-to-install-secure-redis-centos-7

https://golang.org/doc/install

【注意】:MySQL的中文搜索引擎分词在默认情况下有bug,请参考treehollow/treehollow-backend#43 解决

第五步(可选):安装并配置Nginx amplify

Nginx Amplify是一个可以监控服务器健康状态的免费平台,详细介绍和安装方法请见https://amplify.nginx.com/

第六步:注册Google reCAPTCHA

请到https://developers.google.com/recaptcha/intro 分别注册一个reCAPTCHA v3和reCAPTCHA v2 Checkbox,未来将会在后端和前端配置文件中用到

第七步:购买或搭建一个SMTP邮件发送服务器

国外有mailgun和sendgrid,国内有阿里云,也可以自己搭建(可能会很难),具体做法请你根据自身情况搜索

第八步:配置Nginx

本文假设读者已经对Nginx配置文件的结构和用法已经有了基本的了解,下面只介绍几个重点。

重点1:如何让Nginx在CDN后面获取IP

由于服务器只和CDN边缘节点进行网络通信,获取客户IP时就会有难度。还好,几乎所有CDN都会在HTTP的X-Forwarded-For header中转发客户IP。请参考:https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-

但是我们不能完全信任X-Forwarded-For的结果,因为如果攻击者构造一个含X-Forwarded-For的包,就可以达到IP欺骗的效果。为此,Nginx的比较新的版本里都带一个叫ngx_http_realip_module的模块,只要将CDN的IP列表添加进Nginx信任的列表里,就可以正确解析出客户IP。参考:https://cloud.tencent.com/developer/article/1521273

我们在此提供一个脚本,以Cloudflare CDN为例,生成Nginx所需要的配置文件:

#!/bin/bash
echo "# generated by updateNginxWhitelist.sh" > /etc/nginx/whitelist.conf

echo "# Cloudflare IPs" >> /etc/nginx/whitelist.conf
for x in $(curl https://www.cloudflare.com/ips-v4); do echo "set_real_ip_from $x;" >> /etc/nginx/whitelist.conf; done

echo >> /etc/nginx/whitelist.conf

echo "real_ip_header X-Forwarded-For;" >> /etc/nginx/whitelist.conf
echo "real_ip_recursive on;" >> /etc/nginx/whitelist.conf
nginx -t
nginx -s reload

运行此脚本前,在nginx.conf中加入include whitelist.conf;就可以了。如果你看不懂这段脚本在干什么,请先搜索学习相关知识之后,再进行后续步骤。

重点2:如何让Go程序在Nginx后面获取IP

以T大树洞API的/v3/security块为例,Nginx配置文件会类似:

...
    location /v3/security {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;

        proxy_pass http://unix:/somewhere/treehollow-security-api.sock;
        error_page 502 = @fallback;
    }
...
    location @fallback {
         if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' 'https://web.thuhole.com';
            add_header 'Access-Control-Allow-Headers' 'TOKEN';
            add_header 'Content-Length' 0;
            return 204;
         }

        proxy_pass http://unix:/somewhere/treehollow-fallback.sock;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        add_header Access-Control-Allow-Origin "https://web.thuhole.com";
    }
...

如果你看不懂这段配置大概在干什么,请先搜索学习相关知识之后,再进行后续步骤。

重点3:Nginx中Websocket的配置

树洞Android客户端的推送服务使用了Websocket协议的方式,Nginx处理Websocket时的配置应该类似这样:

...
    server_name ws.thuhole.com;
    
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header   X-Forwarded-Proto http;
        proxy_redirect     http:// $scheme://;

        proxy_connect_timeout   3m;
        proxy_send_timeout      3m;
        proxy_read_timeout      3m;

        proxy_pass http://unix:/somewhere/treehollow-push-api.sock;
    }
...

这里如果看不懂没关系,后面会更仔细介绍T大树洞后端的结构

第九步:为树洞后端的运行环境添加新的用户

添加新的低权限Linux用户:

useradd -m username

添加新的MySQL数据库及用户:https://matomo.org/faq/how-to-install/faq_23484/

第十步(可选):下载GeoIP库

T大树洞使用GeoIP库进行风控等操作,这里你如果不知道用什么库,就用免费的Maxmind数据库:https://dev.maxmind.com/geoip/geoipupdate/

安装并运行geoipupdate,然后把geoipupdate放到crontab里

第十一步:下载、编译运行树洞后端代码

树洞后端代码位于https://github.com/treehollow/treehollow-backend

安装方式:git clone下来之后,进入项目文件夹,然后运行:

go install ./...

这时会在$GOPATH/bin生成几个可执行文件,有用的几个分别是:

treehollow-v3-push-api: 用于处理Android和iOS消息推送服务的可执行程序

treehollow-v3-security-api: 用于处理/v3/security 中所有API的可执行程序

treehollow-v3-services-api: 用于处理/v3/ 中security以外API的可执行程序

treehollow-v3-fallback: 当服务更新时,用于向前端显示错误信息的可执行程序

example.config.yml复制到config.yml之后修改参数即可运行。在生产环境中,这四个程序应该都在运行

第十二步【⚠必须采取的安全措施】:配置SELinux

SELinux也许是个讨厌的东西,但它对服务器安全至关重要。为了树洞服务的安全,树洞运营团队的技术人员应该花几个小时学习以下SELinux的使用。这里我们提供一些有用的资料:

学习资料:https://www.digitalocean.com/community/tutorials/an-introduction-to-selinux-on-centos-7-part-1-basic-concepts

实际用的时候其实基本就是用两次audit2allow:https://www.server-world.info/en/note?os=CentOS_7&p=selinux&f=9

(注:如果两次audit2allow不行,那就四次)

第十三步:检查各个域名的正常运行、配置前端的config

T大树洞前端代码位于:https://github.com/treehollow/webhole 配置环境变量之后通过GitHub Actions即可成功运行部署

Android和iOS客户端需要配置文件才能正常运行,请在这个模板下修改:https://github.com/treehollow/thuhole-config/blob/main/main.txt

在T大树洞的生产环境中,至少有8个域名会解析运行:

  1. thuhole.com: 主页
  2. www.thuhole.com: 跳转到thuhole.com
  3. tapi.thuhole.com: 主要API都在这个域名
  4. ws.thuhole.com: Android消息推送时的Websocket服务器
  5. re.thuhole.com: 给app登录时显示reCAPTCHA界面的网页,参考https://github.com/treehollow/thuhole-recaptcha-v2/blob/main/recaptcha/index.html
  6. i.thuhole.com: 显示图片用的域名
  7. web.thuhole.com: 网页版树洞
  8. terms.thuhole.com: 用于放用户协议、隐私政策、树洞规范

把这些服务一个个上线是费时费力的事情,但是生产环境毕竟就是需要这么多服务。