折腾 | 云筏大盘鸡与网站高可用性架构
2020年仿佛是生肖中的老鼠过了现实中的街,大半年的功夫可算是落不得半日安宁,不过灾是这庚子数年的新冠,徒增半年闲时的也是这看似人人喊打的鼠年。总之,不管上半年再糟,也总算是有了忙里偷来大把闲时的大好机会。
窝在家里,终日昏昏沉沉,没啥精神状态,刷刷B站,偶然看到一个UP主,算是对上了胃口,便是征得同意后,给今年的瞎折腾Project中新增了一个项目,创一个同人论坛。
起初是尝试Dz,但是当CMS部署完毕的那一刻我仿佛是回到了2008年的网页,这不得行,必须换。挑来挑去,最终看上了邱君老师的开源ThinkSaaS,原因之一的是里面支持上了Redis,前端用了Bootstrap,总之算是比较新颖的产物了。
望了望CMS,又看回手边的小鸡,貌似剩下的只有套(阿)路(里)云的一台香港了。就是这1C1G的配置实属吃相难看。便是在各种机缘巧合下外加朋友(喂(#`O′)博主,你在无中生友欸.)的安利后,看到了云筏正在卖Hentzer的大盘鸡。
在此之前是对Hz机器适合做后端早有耳闻。今日看到云筏给KVM产品直接给到了3折更是心动不已,脑袋一拍就给下单了(云筏的老平台是Whmcs,那时候都是直接给优惠码,目前是已经迁移了业务系统到Zkeys上)现在回想起来买的时候是2核4G 200GB,找群主Py升级了个500GB大盘,带宽是上下100M的Peer。在过渡到Zkeys以后云筏给了内存翻倍迁移计划。
新的平台(my.cloudraft.cn)给到了2C的E5,8GB DDR4 ECC,500GB(40GB系统+460GB数据)的全新HDD盘 加上 1TB的SSD Cache ,数据还是个是Raid10 阵列,网络是100M上(月5TB流量)300M下(Unlimited流量),宿主机一共给到了32个IPv4 Add,256GB内存,VPS也就只卖32个,0超开这点倒是给我留下了不错的印象。
回题,新鸡到手,免不了一手折腾。先按照惯例看看性能跑分。
从我自己的使用实测来看,网络给到的100M上300M下基本上是能够对接到GD随时跑满的,所以如果是但看数据备份与取回,是无忧的。
而磁盘的读写可以直接如图了:
也是无疑的300MB/s随时跑满
从官方的监控来观察更是无疑的轻负载
重头戏在于云筏自己在Hentzer托管机柜是一个万兆互联,所以一切的故事都要从这里开始。
我的自己手上目前持有的是两台KVM,一台NAT。
所以接下来要做的就是让两台KVM运行Nginx,并互为LB,同时将KVM一号的Session传递进入本机Redis内存储
KVM二号的Session给本机的Redis存储,通过rsync工具,在万兆内网下Redis的数据互通。
并将MySQL数据库的任务交给同机柜但不同网段,使用虚拟网卡完成桥接,并实现内网万兆传输。
同时由于考虑到由于海外的IP没屏蔽,就采用上文的办法,Railgun来完成防御。
梳理完毕,整理出如下图架构:
实际操作:
第一步 | 换源
也是比较重要的,由于云筏的KVM产品CentOS系统默认是清华源,而服务器是Hentzer的欧洲机器,一些需要的源会存在Not found或者速度奇慢无比的现象。
所以必要的是给他换一个源。我在这里直接给准备好了阿里云的源。
备份:
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
下载新的CentOS源,存储到/etc/yum.repos.d/路径下:
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
或者:
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
清除缓存:
yum clean all
生成缓存:
yum makecache
第二步 | 创建服务器之间内网环境
使用vim编辑KVM的内网网卡:
vim /etc/sysconfig/network-scripts/ifcfg-eth1
将 NETMASK
更改为 255.0.0.0
随后使用 systemctl restart network
重启网卡,
并使用 systemctl status network
查看是否已经监听了网卡eth1
(如果是CentOS 6.X设备,需要用service network restart
)
两台KVM设备全部修改完毕后,进入你云筏的后台,新建一个工单申请
“请求为NAT添加一张虚拟网卡,以用作于与KVM实现内网互联”
当然需要注意的是,你的KVM和NAT产品必须是要处于云筏的同一个机柜中
在客服告知你添加完成后,便可以直接去NAT中在/etc/sysconfig/network-scripts/路径下添加一张网卡
ifcfg-eth1
随后,vim编辑这张网卡,
添加如下配置信息:
DEVICE=eth1
ONBOOT=yes
BOOTPROTO=static
NM_CONTROLLED=no
PEERDNS=no
IPADDR=X.X.X.X
NETMASK=255.0.0.0
上述IPADDR为客服为你分配的,写入即可。
以下说一个更加快捷的方法,重装一次NAT系统,便可以被NAT机器自动识别并监听这种新加的虚拟网卡。
但是仍然需要你更改NETMASK的值为255.0.0.0(客服一般会指明为/8)。
重复上述步骤 systemctl restart network
重启网卡,使用KVM去ping NAT机器的内网IP,ping通即为成功。
第三步 | 部署Nginx Web Server
我推荐采用Oneinstack的一键包版本去部署
wget -c http://mirrors.linuxeye.com/oneinstack-full.tar.gz && tar xzf oneinstack-full.tar.gz && ./oneinstack/install.sh --nginx_option 3 --php_option 8 --phpcache_option 1 --php_extensions imagick,fileinfo,redis --redis --reboot
上述将自动安装 OpenResy版本的Ngixn + PHP 7.3 With OPcache + Redis
完成安装后,会自动重启(删除--reboot即可完成不重启)。
或者,你可以根据需求使用SSH完成GUN下的交互安装:
yum -y install wget screen
适用于CentOS或Redhat
wget http://mirrors.linuxeye.com/oneinstack-full.tar.gz
下载安装包
tar xzf oneinstack-full.tar.gz
解压安装包
cd oneinstack
转到目录
(如果需要修改目录,如:安装、数据存储、Nginx日志,则修改options.conf文件)
screen -S oneinstack
如果网路出现中断,可以执行命令screen -R oneinstack
重新连接安装窗口
./install.sh
执行安装
如果你发现此时忘记安装了PHP - Redis拓展,直接输入
./install.sh --php_extensions redis
第四步 | Nginx服务器配置
由于我仅需要为Nginx允许LB的内网IP+CDN的回源IP段。
所以此时需要编辑的Nginx服务器配置。
创建一个list.conf文件,内涵所需要的IP段,例如Cloudflare + 百度云加速的IP列表:
# IPv4
allow 173.245.48.0/20;
allow 103.21.244.0/22;
allow 103.22.200.0/22;
allow 103.31.4.0/22;
allow 141.101.64.0/18;
allow 108.162.192.0/18;
allow 190.93.240.0/20;
allow 188.114.96.0/20;
allow 197.234.240.0/22;
allow 198.41.128.0/17;
allow 162.158.0.0/15;
allow 104.16.0.0/12;
allow 172.64.0.0/13;
allow 131.0.72.0/22;
allow 36.27.212.0/24;
allow 123.129.232.0/24;
allow 119.188.9.0/24;
allow 42.236.93.0/24;
allow 220.170.185.0/24;
allow 115.231.186.0/25;
allow 183.232.51.0/24;
allow 61.182.137.0/25;
allow 112.25.90.0/24;
allow 59.51.81.128/25;
allow 222.216.190.0/24;
allow 122.190.2.0/24;
allow 125.39.239.0/24;
allow 183.61.177.0/24;
allow 183.61.236.0/24;
allow 124.95.168.128/25;
allow 124.95.191.0/24;
allow 58.211.2.0/24;
allow 117.34.13.0/24;
allow 150.138.150.0/24;
allow 150.138.149.128/25;
allow 157.255.25.0/24;
allow 113.207.101.0/25;
allow 111.32.135.0/25;
allow 42.81.6.0/25;
# IPv6
allow 2400:cb00::/32;
allow 2405:8100::/32;
allow 2405:b500::/32;
allow 2606:4700::/32;
allow 2803:f800::/32;
allow 2c0f:f248::/32;
allow 2a06:98c0::/29;
随后添加规则到Nginx下
#仅允许CF的IP访问
include /server/nginx/conf/list.conf;
deny all;
第五步 | 提取静态小文件
一般的CMS静态小文件都存在于public、theme、等目录下的header、footer、head或foot文件内,将它们全部上传至CDN,并将本地路径转化为链接行事即可。
一般情况下,百度云加速的每日10GB流量是足矣的,但是美中不足是Free套餐没移动线路,如果资金充裕,可以前往云筏购他们的百度云加速专业版,一年下来只需660元左右,是官网价格的四折,比现在的官网活动价还要划算,且长期有效,续费同价。
可以点击链接,直接购买,填写我的优惠码,享有额外折扣:9D015C
购买百度云加速CDN 专业版
第六步 | 给网页抗攻击加点料
在你的index.php文件下,头部添加下面展示的代码,将可实现恶意CC攻击IP自动拉入Redis小黑屋屏蔽
//Redis防CC,将恶意IP扔进小黑屋
header('Content-Type: text/html; charset=UTF-8');
//原有代码,此段代码放在下面
//CC攻击停止后会尽快解除验证码,回到正常状态
//防CC配置
$IPmax = 60; //开启验证码条件 值>=php最大进程数,适当设置更大会降低验证码触发条件,但会增大502错误几率(php挂起)
$IPfor = 60; //周期 这个值基本不用动
$IPban = 120; //扔入黑名单 60秒内访问超过60次即拉黑IP
$banTime = 3600*24; //黑名单时长 扔小黑屋时长
$ip = ip();
//连接本地的 Redis 服务
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
//拦截黑名单
if($redis->exists($ip.'ban')){
exit('您被关进了小黑屋,么么哒!');
}
//扔黑名单检测
if($redis->get($ip.'ok') >= $IPban){
$redis->setex($ip.'ban', $banTime, '1');
}
if($redis->exists($ip.'ok')){
$redis->incrby($ip.'ok',1); //记录IP 自增1
}else{
$redis->setex($ip.'ok',$IPfor,1);
}
//按需开启防CC 小黑屋IP不会触发该条件,所以当一段时间以后就会解除验证码。除非攻击者换一批代理继续攻击。如此往复
if(count($redis->keys("*ok")) > $IPmax){
//验证
if($_COOKIE['key'] == ''){
if($_GET['cc']){
$key = md5($ip.$_GET['cc']);
setcookie("key",$key);
}
}
//拦截代码
if($_COOKIE['key'] && $_COOKIE['cc'] && $_COOKIE['key'] == md5($ip.$_COOKIE['cc'])){
//通过
}else{
if($_GET['cc']){
$key = md5($ip.$_GET['cc']);
setcookie("key",$key);
}else{
$cc = rand(1000,9999);
setcookie("cc",$cc);
//这里只是简单的构造了一下验证码,有能力可以自己更改的更安全和完美。
echo '<!DOCTYPE html>
<html>
<body>
<form action="">请输入:'.$cc.' :<input type="text" name="cc" value=""><input type="submit" value="继续访问"></form>
<p> Hey,你的刷新速度太快啦!请输入验证码再尝试继续访问吧~</p>
</body>
</html>';
}
exit();
}
}
function ip() {
if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
$ip = getenv('HTTP_CLIENT_IP');
} elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
$ip = getenv('HTTP_X_FORWARDED_FOR');
} elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
$ip = getenv('REMOTE_ADDR');
} elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
$ip = $_SERVER['REMOTE_ADDR'];
}
$res = preg_match ( '/[\d\.]{7,15}/', $ip, $matches ) ? $matches [0] : '';
return $res;
}
至此,你的基础环境变大功告成了。
敬告⚠:未经允许,严禁搬运