certbot 基于 DNS 验证的自动证书更新

我们之前写过关于通配符域名的证书申请办法,但是没有写怎样自动化更新证书。有人已经写过一个这样的脚本,可以应用于阿里云,腾讯云以及 GoDaddy 的 DNS。 我们以 阿里云为例子,讲一个大概的流程。

把脚本 git clone 到本地,进入克隆目录后:
#  /usr/local/bin/certbot renew --cert-name 证书名 --manual --preferred-challenges dns --manual-auth-hook "`pwd`/au.sh php aly add" --manual-cleanup-hook "`pwd`/au.sh php aly clean"

简单来说,就是以上这句话,如果有问题, 就检查运行目录下的 cerbot.log 文件, 一般会遇到的就是 API Key 的权限有问题。 在阿里云上设置的 RAM 子账户确保有 DNSFullAccess 的权限。

当然, 相信你首先已经创建了这个账户的 AccessKey 以及 Secret 然后更新到 dns.cfg 文件。

我在上面的命令行里, 使用了 –cert-name 通过证书的名称,你当然也可以用 -d 直接指定域名来使用。

有了这个 au.sh 脚本,就等于可以自动化通配符证书的 renew 了, 不用像以前那样,每三个月,需要手工去跑,然后手工去更新 DNS 里的 TXT 记录。

感谢 Let’s Encrypt!

WireGuard Ubuntu 上安装

$ sudo add-apt-repository ppa:wireguard/wireguard (Ubuntu 1910 之后不需要运行)
$ sudo apt install wireguard
$ sudo modprobe wireguard
$ sudo wg show

# 创建 Key Pair 
$ sudo -s
# cd /etc/wireguard; umask 077; wg genkey | tee privatekey | wg pubkey > publickey

服务器端,创建 /etc/wireguard/wg0.conf

[Interface]
PrivateKey = 私钥文本内容
# 服务器端 VPN VLAN 的 IP 地址,带掩码
# 确保 iptable 里面的 eth0 和自己使用的 网卡界面名一致
Address = 10.0.0.1/24, fd86:ea04:1115::1/64
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
SaveConfig = true

用 ufw 管理防火墙 ,并打开包转发

$ sudo ufw allow 22/tcp
$ sudo ufw allow 51820/udp
$ sudo ufw enable
$ sudo ufw status verbose
$ sudo wg-quick up wg0
$ sudo systemctl enable wg-quick@wg0
$ sudo wg show
$ cat << EOF >> /etc/sysctl.conf
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
EOF
$ sysctl -p

以上为服务器配置完成,下面为客户端(可以是 Windows/Mac/iOS/Android等)创建配置文件:

先安装 qrencode 软件包, apt -y install qrencode,生成 png 文件发送给客户端扫码即可配置。

Todo: 部署客户端脚本

基于 unbound 递归 DNS 服务的广告屏蔽(0)

unbound 的好处就是递归,也就是说,所有的 DNS 请求,都是以 unbound 部署点的 IP 直接从 DNS 根服务器上请求,直到请求到合适的 IP 为止,当然中间不排除被掉包。如果我们走 DNSSEC 的话,就会好很多(回头再说 DNSSEC)。

网络上有篇文章关于 FreeBSD 上跑 unbound + adblock 的脚本,可是我们看了下这个脚本,里面其实使用的是陈旧的4年之前的一个老外的黑名单列表。脚本的核心就是根据那个列表用 awk 转换成 unbound 格式的。 其实也是用 awk 的,我们自己写的就是一行代码:

awk '!/^#/ && !/^$/ {print "local-zone:","\"" $1 "\"","static"}' ${BL} > adb.conf

好吧,如果源清单都是陈旧的,没有在更新的,广告屏蔽也就失去了意义。

实际上以上写出来的 .conf 文件不适合 unbound 1.6.x 版本,低版本的 unbound 每个域名需要写两行,这里有个参考的文章。但是使用的都是那个旧的黑名单。

关于加强 ssh 安全的15个最佳实践

原文: https://securitytrails.com/blog/mitigating-ssh-based-attacks-top-15-best-security-practices?from=relatedposts 简要翻译如下:

  1. 不要使用默认的 22 端口
  2. 使用 tcp wrapper
  3. 在防火墙上过滤 ssh 端口,安装 CSF
  4. 关闭 root 登录
  5. 关闭口令登录
  6. 加强口令(如果不能关闭口令登录的话)
  7. 设置 Idle Timeout
  8. 关闭空口令(没有人会这么SB,允许空口令的用户)
  9. 定制一个 ssh 登录 Banner
  10. 自动 Block SSH 暴力攻击,有很多工具可以使用: SSHGuard, Fail2ban, 或者 DenyHosts
  11. 不要在笔记本电脑或者桌面电脑上开启 ssh
  12. 关闭 x11 转发
  13. 设置最多尝试次数, MaxAuthTries 3
  14. 每次root 登录都用邮件提醒
  15. 保持 ssh 软件最新版本

Ubuntu apparmor 导致的 Unbound DNS 服务日志文件不能读写错误

开启 Apparmor 的 debug ,我们就可以在系统日志里看到如下的记录:

Dec 19 11:56:42 localhost kernel: [45483.551927] audit: type=1400 audit(1576727802.918:1755): apparmor=”DENIED” operation=”mknod” profile=”/usr/sbin/unbound” name=”/var/log/unbound/unbound.log” pid=23316 comm=”unbound” requested_mask=”c” denied_mask=”c” fsuid=115 ouid=115

vim /etc/apparmor.d/usr.sbin.unbound
在 root hints 后添加一行:

/var/log/unbound/** rw,

重启 apparmor,重启 unbound 服务后,就可以看到日志能正确的写入了。

解决问题后关闭 Apparmor 的 debug:

echo 0 > /sys/module/apparmor/parameters/debug

再聊 DNS 加密以及广告去除以及黑名单

DNS 黑名单其实是一个很重要的话题,很多人往往忽略。曾经在北美某电子商务大厂(不是A)和内部信息安全部门有业务交往,我们被要求管理一个 DNS 黑名单,在公司内部遇到此类域名解析,一律定向到内部的一个域名,在上面有一个 Web 页面,当然是警告了。

如果企业内部的 DNS 都是自己解析,并且能维护一个黑名单的话,基本上 90% 的网络安全事件都是可控的。 甚至还可以做很多类似 GFW 在做的事情,把 Google.com 给你一个某度的地址。

所以说,你可以脑补一下,这个 DNS 是多么神奇的事情,可以把不想给你看的东西去掉,所以,广告以及有病毒的恶意网站域名都是第一批次就被过滤的。

说了那么多,技术上怎么实现呢? 企业内部有 IT 可以做自己的 DNS 服务器,个人家庭网络,要怎么做才能过滤广告,才能安心看片呢?

基本上,你需要一个能安装 Linux 的小盒子,放在光猫旁边,把光猫的 DHCP 功能去掉,把这个 Linux 小盒子通过无线或者有线连接到光猫上,然后 Linux 上启动 DHCP 和 DNS 服务功能。

那么这个 Linux 小盒子,有哪些不同的实现形式呢?最常见的就是能刷机的路由器,例如斐讯的K2 比较常见,华硕的很多也能刷机。这里列出一个能刷 OpenWrt Linux 操作系统的最新版本的一些无线路由器列表,最后两列为 Flash 和内存是购买时要主要考虑的。

我们知道,我们上网时,一般都是要走运营商的 DNS 来解析的,就算我们不使用运营商的,很多人会使用公共 DNS 服务器, 例如 114.114.114.114,但是他们并不能保证我们的 DNS 解析是安全的,而且类似 Google 的域名也是基本被“拐”的,就算有的人知道使用 Google 的 DNS 服务器 8.8.8.8/8.8.4.4 ,但是 DNS 解析本身是不安全的,也就是说,你看过的网站,运营商还是能知道你访问了哪些网站。

那怎么解呢?我们就需要在 Linux 小盒子上安装 Go 语言编写的 DNSCrypt-Proxy 这个免费软件。通过名称就可以知道,它是对 DNS 解析做加密的,能从网络上已知的 DNS 加密服务器上做解析,完全绕过了运营商,而且做了加密。

安装了这个软件,指定了黑名单以后,你就会感觉网页是清爽很多,没有什么狗皮膏药了。

譬如我们看 YouTube,按 F12, 就可以看到很多被屏蔽的域名。

譬如我们看新浪的一则新闻,屏蔽的内容就更多

指定黑名单其实不难, git clone 项目地址,里面有一个公共的黑名单清单, util 目录下还有一个 Python 脚本能自动生成这个黑名单。

企业和个人对这个方案有兴趣的可以关注我们公众号,并留言哦!

DNSCrypt 的黑名单机制,能有效的去除广告以及恶意网站。 不过,对于有些原生的广告图片嵌入, DSNcrypt 确实还是没有效果的,因为此类广告和页面内容的域名是同一个,你总不能因噎废食,把所有正常内容都过滤掉吧。 所以 DNSCrypt 是一个小盒子上的“硬件”解决方案,对于此类特殊的过滤,还是需要浏览器里的广告去除插件来进一步净化环境。

以 Sohu.com 首页下半部娱乐版块内嵌的广告为例,这是使用了 Adblock 以后什么广告都没有的情形:

这是没有使用 Adblock 插件时,小部分广告图片依然有展示。

云端安装 HTTP 代理 clash 解决后端连接境外网站缓慢的问题

clash 是用 Go 语言写的一个全面的代理服务器,支持多种代理协议。理论上也是一个很好的代理转换工具。假定我们在云端已经安装了一个 v2ray 的 socks5 服务。v2ray 本身是不提供 http proxy 的,但是在我们某些软件的配置,只能使用 http 代理,这个时候,我们就必须使用 clash 来对付了,理论上,如果我们使用了 clash,就可以放弃使用 v2ray 客户端了, 因为 clash 也是支持 vmess 协议的。

这里我们假定 clash 继续使用 v2ray 的本地 socks5 服务,由 v2ray 实现和境外服务器 v2ray 服务的对接。

去 clash github 官网下载最新版本的 release, .tar.gz 解压。 chmod +x ,并把文件移动到 /usr/bin/clash , 创建 /etc/clash 目录,编辑里面的 config.yaml 文件如下:

把 clash 添加为服务,编辑 /lib/systemd/system/clash.service 如下:


然后systemctl daemon-reload; systemctl –now enable clash; systemctl status clash 查看进程状态。
校验是否能访问 Google:
# https_proxy=127.0.0.1:8888 curl -kIsS https://www.google.com/ 看是否能访问 Google 就可以了。

clash 有很多玩法, 这里只是最简单的一个本地 socks5 代理转化为 http 代理的一种方式, tinyproxy 是不支持后端 socks5 的, polipo 虽然也支持, 但是这里写 clash 的目的其实是想在服务器上只安装一个 clash 服务, 去掉 v2ray。

另外, v2ray 也支持 mKCP 协议, 把原先的 tcp 转化为 UDP, 具体就是 v2ray 客户端的配置里,在 outbounds 的 settings 后面添加 streamSettings,当然服务器端是在 inbounds 做对应的配置。

通过 ssh 的隧道跳板机

绕过跳板机,一步直达目标主机

上次在公众号发了一段话讲了怎样从外部访问公司内服务器:

在办公室机器上打一个隧道到公网服务器上。 回家后登录到公网服务器,从那里直接就连接到公司的服务器了。 公司内服务器运行: user_internal@server_in_office$ ssh -f -N -R 2222:localhost:22 user@host.qcloud.com 腾讯云上服务器,运行 $ ssh -p 2222 user@localhost 就能进入办公室服务器了。 user 可以是办公室搭桥的服务器上任意的用户,不一定是当时搭桥的用户。 搭桥的 ssh 命令可以用 autossh 命令替换。

但是如果要从其他地方进入公司的服务器,每次都要先登录到云端,再在云端的服务器上运行上面的命令,是不是多了一个步骤? 解决方案来了:

ssh -o ProxyCommand=”ssh -W localhost:2222 user@host.qcloud.com” server_in_office

man ssh 对 -W 参数是这么解释的:

这是公司内服务器对外不暴露 ssh 端口的情形下的解决方案,当然,如果公司内服务器直接对外暴露 ssh 端口,就无需以上跳板,连第一步也是多余的了。

至于公司内 IP 地址经常变动,怎样获得相对不变的域名,一般都是 DDNS 的解决方案,我们采用 GoDaddy 的 API,把注册在 GoDaddy 上的二级域名,用定时任务检测到内部 IP 地址变化时,自动更新域名。
该脚本全文已经放在 github, 欢迎 fork and star.