使用 Let‘S Encrypt 为您的网站申请免费证书

网站的https证书过期了,一直使用阿里云的免费ssl证书,但是现在阿里云调整了策略,证书有效期从1年缩短到3个月了,所以我决定放弃阿里云转而使用 Let’s Encrypt 申请免费证书。 简介 Let’s Encrypt 是一家免费、开放、自动化的公益性证书颁发机构(CA), 由互联网安全研究组(ISRG)运作,详细介绍可以看这里。 申请证书 按照官方文档,对于没有命令行访问权限的网站,比如wordpress、cPanel等,可以通过控制台设置或者申请后手动上传证书;而我的网站服务器托管在阿里云,拥有命令行访问权限,所以直接使用官方推荐的 Certbot ACME 客户端来管理证书,这里详细记录下步骤。 CertBot 文档有详细的安装步骤,我的 ubuntu14 上的步骤如下: 安装 snapd snap 是linux的应用程序包,可以从其自身的snap store中安装、管理软件,有点类似包管理器如 apt、yum,但是不依赖linux发行版,安全、跨平台且无依赖;而 snapd 则是一个自动管理和维护 snap 的后台服务,它们之间的区别请参阅官方文档。 Ubuntu 16.04LTS版及之上的版本已经集成了snapd,无需再安装了,而我的是 14,所以需要手动安装。 sudo apt update sudo apt install snapd 测试是否安装成功,可以安装官方的 hello-world 程序: $ snap install hello-world 2024-06-09T16:15:39+08:00 INFO Waiting for automatic snapd restart... hello-world 6.4 from Canonical✓ installed 执行并成功输出信息表示安装成功: $ hello-world Hello World! 删除 certbot-auto 和任何 Certbot OS 软件包 如果您使用操作系统包管理器(如 apt 、 dnf 或 yum 安装了任何 Certbot 包,则应在安装 Certbot snap 之前删除它们,以确保运行命令 certbot 时,将使用 snap,而不是从操作系统包管理器进行安装。执行此操作的确切命令取决于您的操作系统,但常见的示例是 sudo apt-get remove certbot 、 sudo dnf remove certbot 或 sudo yum remove certbot 。 ...

2024-06-09 · 2 min · 374 words · Hank

Redis集群中的 CROSSSLOT Keys Error

场景 Redis单节点没有问题,切换到Redis Cluster后业务上某一功能出错: CROSSSLOT Keys in request don't hash to the same slot 出错的代码: 1 2 3 4 5 6 7 8 var ctx = context.TODO() _, err := uq.queueImpl.rc.TxPipelined(ctx, func(pip redis.Pipeliner) error { cmd := pip.LPush(ctx, uq.key, dest...) if cmd.Err() != nil { return cmd.Err() } return pip.SAdd(context.Background(), uq.setkey, dest...).Err() }) 这段代码的逻辑是向 list 中push一条数据,再向一个 set 加入数据,两步操作通过 pipline 在同一个事务中完成。 问题分析 错误的大概意思就是: 请求中跨槽的key没有被hash到相同的hash槽中。通过代码分析,事务中的两次操作的key并不相同,他们没有被hash到同一个hash槽从而出现上述错误。 什么是hash槽 Redis Cluster 规范中的 Key distribution model(key分布模型)说明如下: Redis集群中将key的存储空间划分为16384个slot,整个集群可以支持最大16384个主节点,实际上建议不超过1000个节点。每一个主节点又可以处理16384个 hash slot。整个集群将hash slot分布于不同的节点组成高可用集群,单个节点有多个副本以便在节点故障时将重新平衡节点,达到高可用的目的。关于可用性保证,可以看这里。 如下的公式用于计算key的hash slot: HASH_SLOT = CRC16(key) mod 16384 Redis将相同hash值的slot分布到同一个node下,如下图所示: 图片出自这里 可以看出,hash槽(slot)就是一个整数,通过key计算得来,它的作用就是决定key存储于哪一个节点中。 为什么会出现CROSSSLOT错误 主要原因是应用程序尝试在多个键上运行命令,但操作中涉及的键不在同一个哈希槽中,这会导致集群中不允许的“CROSSSLOT”操作。 比如,使用Set的SUION命令时,如果多个key的 hash slot 不在集群中的同一个node上,则会出现CROSSSLOT错误。 前边场景中,在同一个事务中操作多个key,集群环境下必须要保证这些被操作的key必须被hash到同一个slot,否则同样会抛出CROSSSLOT错误。 Redis这么做的主要原因还是在于避免分布式数据被破坏的风险,而且在同一个事务下或者同一个命令中操作多个跨节点的key,会因网络等因素带来性能损耗,所以Redis禁止这么做。如果有这种场景,Redis也提供了解决方案:使用Hash Tags。 ...

2023-10-17 · 1 min · 131 words · Hank

Nginx Bad Gateway和no live upstreams错误分析

最近项目的生产环境中客户端出现大量的Nginx 502 Bad Gateway错误,逐步排查最终定位到是由于被ddos攻击造成服务器资源耗尽无法响应造成的问题。遂整理过程著文以记之。 场景 线上4个节点,每个节点都有两个相同服务通过Nginx作负载均衡,均采用Nginx默认值,未做过多配置,配置类似: 1 2 3 4 upstream test-server { server 127.0.0.1:8002; server 127.0.0.1:8001; } 客户端出现大量的 502 Bad Gateway 信息,查看Nginx错误日志,信息如下: no live upstreams while connecting to upstream 初步定位问题,发现后台出现了很多莫名其妙的错误,查看Nginx错误日志发现也打印了很多上述错误。怀疑是后台某个接口请求出错导致返回了 500,导致Nginx将这个服务下线,后经过排查,后台确实存在一些错误信息,但是出错上述错误的时间不匹配。 后整理思路并认真思考,发现可能思路存在偏差:后台http状态码怎么会影响Nginx将服务下线呢? 因为Http状态码表示http响应的状态,也就是表示响应结果的正确与否,比如 2xx 表示服务端正确处理并响应了数据,4xx 表示客户端存在错误妨碍了服务端的处理,5xx 表示服务端错误导致处理失败了。但是,能够返回这些状态码说明服务端连接正常,只是由于特定原因导致服务端响应错误了。返回了这些状态码Nginx当真会将服务下线吗?试想一下,某一个客户端请求查询一条不存在的数据导致服务端处理时抛出异常并响应 500 状态码,然后Nginx认为服务不可用并将其下线,导致一定时间内所有的请求都返回上述错误,那么罪魁祸首到底是服务端还是客户端?Nginx这么处理是不是太过了呢?Nginx肯定不会这么来设计。 所以,我猜测Nginx不可能如此是非不分,应该是别的原因导致的。 查阅upstream官方文档,看到这么两个参数配置: fail_timeout=time: 设置多少时间内不能与下游服务成功通信 max_fails 次后可以认为下游服务不可用,这是一个周期时间,即每隔 fail_timeout 时间都会进行统计,默认为 10 秒。 max_fails=number: 设置在 fail_timeout 时间内与下游服务通信失败的次数,达到该次数后认为服务不可用,默认为1。 按照Nginx的默认设置,也就是说每个10秒统计下有服务的通信失败次数,达到1次就认为服务不可用,此时Ngingx会将其踢下线,后续所有转发到该服务的请求都会返回 no live upstreams while connecting to upstream,直到下一个10秒再重新处理(max_fails 为0又重新将服务上线)。 关键在于这个 通信失败 的理解。通信失败,表示Nginx转发请求给服务,但是服务没有任何响应,而不是一开始怀疑的 HTTP 状态不是200,能成功响应,不论是什么状态码,都应该认为与服务通信成功。 实践才能出真知,为了验证我的猜想,必须进行实验。 ...

2023-10-07 · 5 min · 990 words · Hank

使用TpLink的DDNS让外网访问本地服务

1. 背景 很多时候,我们需要将本地服务暴露给外网访问,或者简单地说能够通过互联网访问本地电脑。比如,公司内网有一台服务器,上边的多个服务都需要在公司和在家里都能访问到,如代码库、数据库等;又比如,在开发微信公众号此类需要外网回调本地环境的应用,如果能够将本地服务暴露给外网访问,那么调试起来将非常方便。 目前,市面上有许多工具软件,能够实现上述目的,但是,一方面稳定性欠佳,另一方面几乎都需要付费,不能作为长期使用。 所以,本文介绍的是,如何使用TpLINK路由器提供的DDNS [1] 功能,改造家里的电信网络,将家里的电脑暴露给外网。 2. 准备 原网络服务商为电信,需要有电信光猫、一台TpLINK路由器(支持DDNS [1])、网线。由于我家里的网络原来都是已经连接好的,电信光猫下接了路由器,通过电信光猫和路由器都可以上网,所以本文是基于此来进行网络配置修改的,全部使用的是笔记本的无限网络访问路由器和光猫,并没有用网线直连光猫和路由器。 3. 整体思路 将电信光猫上网方式由原来的“路由”改为“桥接”,让其仅充当交换机的作用;然后配置TpLink路由器,所有的上网都通过TpLink而不是光猫;然后利用TpLink的DDNS和虚拟服务器功能,将本地端口映射到外网,通过DDNS域名就可以访问本地服务了。 4. 实现步骤 在我的网络环境中,以电信光猫为中心,下边连接了多个路由器,包括一台TpLink路由器,路由器和光猫都可以上网,具体怎么实现上述结构的请查阅相关资料。路由器地址:192.168.0.1,电信光猫地址:192.168.1.1。 4.1. 破解电信光猫 首先,电信光猫默认的useradmin账号登进去的权限很有限,不能修改网络设置。所以,我们需要破解之,为修改上网方式做准备。 使用useradmin和密码登录光猫(用户名和密码在光猫背面,一般为useradmin),然后访问http://192.168.1.1/backupsettings.conf,此时会下载光猫配置文件; 用记事本等文本工具打开,搜索TeleComAccount,然后你会看到如下的配置: <X_CT-COM_TeleComAccount> <Password>8MAB1223</Password> </X_CT-COM_TeleComAccount> Password就是光猫管理用户telecomadmin的密码,记录下来备用。 然后,再搜所Username,找到如下配置: <Username>CD68458918</Username> <Password>aAg0xDgADTgA</Password> 其中,Username就是宽带拨号上网的账号,Password就是其密码,不过是Base64的密文,在线找一个BASE64解码网站,就可以得到原始密码,记录下来备用。 然后,把http://devacs.edatahome.com:9090/ACS-server/ACS找到(只有一处),改成http://devacs.edatahome.com.disable:9090/ACS-server/ACS,使得无法连接远程管理服务器,然后找到 <TotalTerminalNumber>5</TotalTerminalNumber> 把5改成一个比较大的数字用以解除光猫接入设备数量限制。 最后,通过前边的telecomadmin和找到的密码,登录光猫,访问http://192.168.1.1/updatesettings.html,选择刚才修改的配置,让光猫启用最新配置(过程大概需要2分钟)。 ok,光猫破解完成。 4.2. 修改电信光猫桥接上网 光猫完成破解后,通过telecomadmin登录,找到状态菜单-用户侧信息,可以查看到当前WAN连接信息,如下图所示: 找到TpLink路由器连接的对应WAN连接,我这里是上边红框部分,截图是我已经修改成了桥接模式,所以地址获取方式一栏写的是BRIDGE。 然后,点击网络-网络设置,连接名称选择上边确定的TpLink连接的WAN连接,然后将连接模式改为桥接,如下图所示: 其他不用做任何修改。 保存过后,现在光猫是不能上网的,接下来,需要配置路由器上网。 4.3. TpLink宽带拨号上网 访问http://192.168.0.1,登录TpLink,点击左侧上网设置菜单,修改上网方式为宽带拨号上网(原来是默认的自动获得IP地址),如下图: 宽带账号和密码分别填入前边 #netaccount[破解光猫时]找到的宽带账号和密码,然后点击连接按钮。 现在,路由器可以正常上网了。但是由于更改了网络配置,现在不能通过192.168.1.1访问光猫了,要WIFI访问光猫,把路由器的上网方式还原为自动获取IP地址即可。 4.4. TpLink #ddns[DDNS]配置 点击路由器下边的应用管理,找到DDNS,点击进入,如图所示: 看到的界面如下: 服务提供商选择TP-LINK,在我的域名下会显示当前登录的DDNS域名,如果没有,点击创建新域名,然后登录即可,具体DDNS使用可以看 这里。 4.5. TpLink虚拟服务器端口映射 DDNS有了,但是还不能访问内网服务,还需要在路由器上做端口映射,将内网端口暴露到外网。 同样在应用管理,找到虚拟服务器,进入后可以看到如下图所示界面: 外部端口:外网能够访问的端口 内部端口:内部服务的端口 添加完成后,现在通过[DDNS域名]:[外部端口]就可以访问内网服务了,我这里是 http://belonk.tpddns.cn:8088。 大功告成!! 5. 结束语 TpLink目前是自带了DDNS,可以免费申请DDNS域名,免费而且稳定。在使用的时候,需要将TpLink路由器作为上网源,光猫只是充当交换器而不提供路由功能。 1. DDNS(Dynamic Domain Name Server)是动态域名服务的缩写。DDNS是将用户的动态IP地址映射到一个固定的域名解析服务上,用户每次连接网络的时候客户端程序就会通过信息传递把该主机的动态IP地址传送给位于服务商主机上的服务器程序,服务器程序负责提供DNS服务并实现动态域名解析。 ...

2018-06-09 · 1 min · 72 words · Hank

ubuntu下ssh关闭密码登陆,采用公钥认证登陆

前段时间,公司内网的机器被黑客入侵,最后分析原因,在于我们希望通过外网访问公司的git仓库,然后开放了22端口,而此前git所在机器上被病毒感染过…… 由于git是单独的服务器,所以我们希望只有公钥认证的用户可以授权访问该服务器,否则拒绝访问。因此,我们决定采用以下方案: 禁止用户通过ssh的账号密码登陆,而是用公钥私钥认证登陆。具体做法如下: 1. 修改SSH配置文件sshd_config 注意是sshd_config,修改ssh_config无效 编辑sshd_config文件: $ vi /etc/ssh/sshd_config 禁用密码验证,默认是yes $ vi /etc/ssh/sshd_config 启用密钥验证 $ vi /etc/ssh/sshd_config 指定公钥数据库文件 $ vi /etc/ssh/sshd_config 2. 重启ssh服务 $ vi /etc/ssh/sshd_config 由于服务器有两个用户:root管理员用户和git用户,而所有访问代码的必须通过git用户访问,git本身已经通过公钥私钥登陆,所以对原来访问代码仓库的客户端没有影响。而目前root用户禁止了密码登陆,如果进行授权呢? 很简单,将授权以root用户登录服务器的客户端公钥加入到/root/.ssh/authorized_keys文件中,客户端登陆时,带上客户端的私钥信息,就可以完成认真并成功以root用户登录,我用的mobXterm工具,其他工具类似,链接选择私钥如下: 这样,就完成了只能公钥认证通过的用户才能登陆服务器的功能。 3. 注意事项 3.1. 保留会话窗口 在修改sshd_config文件并重启ssh之前,先保留一个链接到服务器的会话,否则如果ssh配置出现错误,将导致不能链接到服务器。 3.2. ssh配置文件 修改sshd_config而非ssh_config。 3.3. 为何不修改ssh默认的22端口 因为链接git仓库客户端较多,如果修改了22端口,每一个客户端都要重新设置代码仓库的remote地址,处理起来较为麻烦,如果如何处理请自行百度。当然为了更为安全,建议还是修改ssh默认的22端口。

2017-08-14 · 1 min · 41 words · Hank

Nginx学习——nginx的下载、安装和启动

Nginx作为一款轻量级WEB服务服务器,除了作为http代理和反向代理服务器,还更广泛的运用于负载均衡、高级http服务、邮件代理服务等。接下来,我们开始学习如何下载安装Nginx服务器,包括windows平台和linux平台。 1. Nginx版本 Nginx的官方网址: http://nginx.org Nginx下载地址: http://nginx.org/en/download.html 如上图所示,目前nginx官方分为三个版本: 主线开发版本(Mainline version):即功能较新的处于开发中的版本,可以用于学习,但不太稳定,不适合商用; 稳定版本(Stable version):功能稳定,适合商用; 历史遗留版本(Legacy versions):较早的历史版本。 其他链接 图1中的CHANGES的链接,是对于此版本的更新日志记录; 图1中的nginx-x.x.x的链接,对应的是nginx特定版本的源代码; 图1中的pgp链接,记录的是使用GPG加密软件计算后的签名信息,用于下载文件的验证,防止文件被篡改; 图1中的nginx/Windows-x.x.x对应的是nginx的windows版本的下载链接。 2. Windows 1、下载安装 下载图1中的nginx/Windows-1.12.0,得到window版本的nginx压缩包。 windows版本为绿色版本,解压即用,无须安装。解压下载的压缩包,得到如下的目录结构: 2、启动 双击nginx.exe启动 直接运行图2的nginx.exe即启动了nginx,同时可以在任务管理器中看到有两个nginx.exe的进程。 Windows命令行启动 运行cmd,进入nginx目录,运行命令 $ nginx.exe 这种方式会使命令行一直处于执行中,无法进行后续操作 或者 $ start nginx 推荐的方式。 如果启动未出现异常信息,表明启动成功,任务管理器中会出现两个nginx.exe的进程。 3、停止 杀进程 直接在任务管理器中kill掉nginx进程,不推荐。 命令行 运行cmd,进入nginx目录,输入命令 $ nginx.exe –s quit 推荐,这种方式是平缓停止,完整有序的停止nginx,并保存相关信息 或者 $ nginx.exe –s stop 快速停止nginx,不保存相关信息。 4、重新加载配置文件 运行cmd,进入nginx目录,输入命令 $ nginx –s reload 5、重新打开日志文件 运行cmd,进入nginx目录,输入命令 $ nginx –s reopen 6、Nginx版本查看 $ ./sbin/nginx –v 或者 $ ./sbin/nginx –V ...

2017-05-15 · 2 min · 269 words · Hank

linux常见操作整理

Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的UNIX工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。本文记录了Linux常用的一些命令,并不断完善中,以备查阅。 1. 基本操作 1、删除文件命令: rm -rf 目录循环删除目录 2、打开/关闭fpt命令: service sftpd stop/start 3、ftp开启命令: /etc/rc.d/init.d/xinetd stop /etc/rc.d/init.d/vsftpd start /etc/rc.d/init.d/xinetd start 4、svn开启命令: svnserve -d -r /usr/local/svn/ 5、jetty启动: root@ubuntu-server1:/usr/local/jetty-mvn/jetty9/bin# ./jetty.sh start Starting Jetty: . . . OK Tue Sep 10 12:30:45 CST 2013 6、解压文件到指定目录: tar xxx.gz -C /usr/local/ 7、查看权限命令 查看目录的相关权限可以采用命令ls -lD,或者直接用ls -la如: ls -l www.jb51.net 这里表示查看www.jb51.net目录 8、查看linux机器是32位还是64位的方法: file /sbin/init 或者 file /bin/ls 9、找不到网卡解决: vi /etc/udev/rules.d/70-persistent-net.rules 将最新的eth2网卡改为eth0,并拷贝其ATTR(即最新的mac地址)值,然后编辑eth0的配置文件,将HWADDR改为该值,重启网络服务,问题解决。 10、查看磁盘空间: df -hl 11、查看系统用户和组: groups查看当前登录用户的组内成员 groups gliethttp查看gliethttp用户所在的组,以及组内成员 whoami查看当前登录用户名 /etc/group文件包含所有组 /etc/shadow和/etc/passwd系统存在的所有用户名 ...

2017-04-05 · 4 min · 694 words · Hank