loyess / Shell

Shadowsocks with plugins one-click installation. e.g. v2ray-plugin, kcptun, simple-obfs, goquiet, cloak, mos-tls-tunnel, rabbit-tcp, simple-tls, gost-plugin, xray-plugin, qtun, gun
783 stars 356 forks source link

SSL certs are not updating #87

Closed jeffshead closed 2 years ago

jeffshead commented 2 years ago

I have three sites using your script. The cert on all three sites expired today. With previous version of script, never had issue with certs. Used to always update prior to 90 days. No longer working. Certs no longer update.

loyess commented 2 years ago

证书是由acme.sh申请的,默认会添加自动续期证书的定时任务。

# 终端执行此命令查看定时任务列表。
crontab -l

# 输出类似如下信息,意味着定时任务已被添加。
42 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

后缀为 .cf .ga .gq .ml .tk 的域名,在CDN模式下,证书不会自动续期。

jeffshead commented 2 years ago

Thank you for response. The cron job does exist. However, I think issue is caused by ss-plugins.sh script switching from RSA cert to new ECC cert. Old RSA cert not removed when updating server with newer ss-plugins.sh script so cert renewals fail.

loyess commented 2 years ago
  1. 域名仅绑定vps的ip时,申请证书命令
    
    # 变量
    domain="your-domain.com"

RSA

acme.sh --issue -d ${domain} --standalone

ECC

acme.sh --issue -d ${domain} -k ec-256 --standalone


2. 域名绑定vps的ip 经过 CloudFlare CDN 代理时,申请证书命令

变量

domain="your-domain.com" export CF_Email="your-cloudflare-account-email" export CF_Key="your-cloudflare-account-global-api-key"

RSA

acme.sh --issue --dns dns_cf -d ${domain}

ECC

acme.sh --issue --dns dns_cf -d ${domain} -k ec-256


3. 以下是手动模式,为后缀为 .cf .ga .gq .ml .tk 的域名 申请CDN证书时的指令。(不支持 自动续期证书)

变量

domain="your-domain.com"

RSA

acme.sh --issue --dns -d ${domain} --yes-I-know-dns-manual-mode-enough-go-ahead-please

根据上一条指令提示,在CloudFlare后台添加txt记录后执行下一条命令

acme.sh --renew -d ${domain} --yes-I-know-dns-manual-mode-enough-go-ahead-please

ECC

acme.sh --issue --dns -d ${domain} -k ec-256 --yes-I-know-dns-manual-mode-enough-go-ahead-please

根据上一条指令提示,在CloudFlare后台添加txt记录后执行下一条命令

acme.sh --renew -d ${domain} --ecc --yes-I-know-dns-manual-mode-enough-go-ahead-please


4. 使用acme.sh证书续期指令,强制续期证书。

acme.sh --cron --force


5. 删除证书指令

变量

domain="your-domain.com"

RSA

acme.sh --remove -d "${domain}" rm -rf /root/.acme.sh/${domain}

ECC

acme.sh --remove -d "${domain}" --ecc rm -rf /root/.acme.sh/${domain}_ecc



做个小测试,你可以使用以上命令,去申请 RSA 和 ECC 类型的证书,使之同时存在。
然后,使用续期指令,强制证书续期,如果没有报错,证明并不是 RSA 和 ECC 同时存在导致的证书自动续期失败。

另外,说明一下,脚本中之所以没有删除证书的步骤,也是为了防止太多次申请证书,导致出现限制无法申请的状况。
这也确实存在一些问题,例如;域名状态先为 dns-only,后又改成了cdn ,申请证书就可能会有问题(并不确定)。

现在 qtun 这个插件还不支持 ECC 的证书,两种申请方式都在脚本中保留了,属实有点乱。优先保证脚本能用吧,其它的细节不大想改,也不太好改。其实,本来用 RSA 就挺好的。

注意:
    请不要尝试申请证书太多次,否则,超出每个注册域名可签发证书数量限制的请求,将会得到 too many certificates already issued 的报错信息
    具体可以参考:[Rate Limits](https://letsencrypt.org/docs/rate-limits/)
jeffshead commented 2 years ago

Thank you! Prior to your latest response, I removed the RSA cert and issued an ECC cert. That seems to work. However, I get the following if I try to add the RSA cert as per your instructions:

# acme.sh --issue -d ${domain} --standalone
[Sun Jan  2 08:45:55 EST 2022] The domain 'xxx.com' seems to have a ECC cert already, please add '--ecc' parameter if you want to use that cert.
[Sun Jan  2 08:45:55 EST 2022] Using CA: https://acme-v02.api.letsencrypt.org/directory
[Sun Jan  2 08:45:55 EST 2022] Standalone mode.
[Sun Jan  2 08:45:55 EST 2022] LISTEN 0      128                *:80               *:*    users:(("caddy",pid=1378,fd=8))
[Sun Jan  2 08:45:55 EST 2022] tcp port 80 is already used by (("caddy",pid=1378,fd=8))
[Sun Jan  2 08:45:55 EST 2022] Please stop it first
[Sun Jan  2 08:45:55 EST 2022] _on_before_issue.
loyess commented 2 years ago

80 端口被 caddy 占用了,使用acme.sh 的 --standalone 参数,去申请证书,需要使用到80端口。另外,如果报错找不到 socat,安装socat。

jeffshead commented 2 years ago

socat is already installed.

# rpm -qa |grep socat
socat-1.7.4.1-1.el8.x86_64

I entered port 443 when prompted by ss-plugins.sh script during installation so I don't know why it says Caddy is listening on port 80. Below is my Caddyfile:

sub.domain.tld:443 {
   header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains"
        -Server
    }

    encode gzip
    log {
        output file /var/log/caddy-access.log
        format json
    }
    tls /root/.acme.sh/sub.domain.tld_ecc/fullchain.cer /root/.acme.sh/sub.domain.tld_ecc/sub.domain.tld.key {
        protocols tls1.3
    }
    reverse_proxy /v2ray localhost:12413
    #reverse_proxy https://www.bing.com {
    reverse_proxy 127.0.0.1:81 {
        #header_up Host {http.reverse_proxy.upstream.hostport}
        #header_up X-Real-IP {http.request.remote}
        #header_up X-Forwarded-For {http.request.remote}
        #header_up X-Forwarded-Port {http.request.port}
        #header_up X-Forwarded-Proto {http.request.scheme}
    }
}

I get the same results even if I remove the following from Caddyfile and reboot:

header {
    Strict-Transport-Security "max-age=31536000; includeSubDomains"
    -Server
}

I also have the following in httpd.conf:

Listen 81
ServerName sub.domain.tld:81

Below is active firewall rules:

# firewall-cmd --zone=public --list-all
public (active)
  target: DROP
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services: http https
  ports: 443/tcp 443/udp
  protocols:
  forward: no
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
        rule family="ipv4" source address="x.x.x.x/24" port port="22" protocol="tcp" accept
        rule family="ipv4" source address="x.x.x.x/28" port port="22" protocol="tcp" accept
loyess commented 2 years ago

caddy2官方文档,关于端口的介绍:

Caddy's default port is no longer :2015. 
Caddy 2's default port is :443 or, if no hostname/IP is known, port :80. 
You can always customize the ports in your config.

Caddy 2's default protocol is always HTTPS if a hostname or IP is known. 
This is different from Caddy 1, where only public-looking domains used HTTPS by default. 
Now, every site uses HTTPS (unless you disable it by explicitly specifying port :80 or http://).

来源:HTTPS and ports

caddy 配置中第一行,已经指定了 域名 和端口,按理说caddy应该是不会使用到80端口的。

lsof -i:80

可用上面这条命令查看80端口在被那个进程给占用。

jeffshead commented 2 years ago

可用上面这条命令查看80端口在被那个进程给占用。

# lsof -i:80
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
caddy   1382 root    8u  IPv6  22087      0t0  TCP *:http (LISTEN)
loyess commented 2 years ago

这不就是caddy占用了么,直接kill掉吧,之后观察看看进程会不会自动启动。或者kill 掉之后,重启caddy后,看这个进程是否还在。

loyess commented 2 years ago

我试了下,caddy确实会同时监听80端口。

jeffshead commented 2 years ago

I am confused. How do I fix this?

loyess commented 2 years ago

或许可以写个小脚本,去替代acme.sh定时任务,在执行续期命令前,停止caddy nginx之类的服务,执行续期命令前之后再给启动。

刚看了下acme.sh的文档,发现有一个 --httpport 参数可以在使用 Standalone mode 申请证书时,指定端口,可以考虑在申请证书时,指定非80端口。

例如这样:

# 变量
domain="your-domain.com"

# RSA
acme.sh --issue -d ${domain}   --standalone --httpport 88

# ECC
acme.sh --issue -d ${domain} -k ec-256 --standalone --httpport 88

还未测试过是否可行,如果可以的话,会在脚本中改改。

另外防火墙,也要打开这个端口才行。

似乎还是写个小脚本替代,省事点。手动续期也不错。就我个人来说,对这个定时续期没太大需求,因为,几乎没有过了3个月都不登陆服务器的情况。连接服务器也很方便,手机都能操作。偶尔看到了,证书快过期了,就给手动续期一波。当然,服务器多的可能就有些麻烦。

jeffshead commented 2 years ago

Thanks again. Caddy can manage its own certs (by default) so having a stand-alone version of acme.sh seems to be redundant. I replaced the following line in /usr/local/caddy/Caddyfile and Caddy automatically issued a new cert upon restart:

...
#tls /root/.acme.sh/sub.domain.tld_ecc/fullchain.cer /root/.acme.sh/sub.domain.tld_ecc/sub.domain.tld.key {
tls {
    protocols tls1.3
}
...

The tls directive can be removed completely but I decided to only remove the portion which points to the stand-alone cert so that I can test with TLS1.3. It seems that not all browsers support TLS1.3 and Qualys lowers the test score if TLS1.2 is not supported so removing the entire tls directive may be a better option for compatibility.

This is an easy, manual fix for Caddy users to ensure there's no downtime due to an expired cert. Do you think letting Caddy manage its own certs would be a worthwhile change to your installation script?

loyess commented 2 years ago

脚本最初就是让caddy自己管理的证书,后来才用acme.sh管理的,不会改回去了。

而且,我已经修改了脚本,在这个 9b8d8a2 提交里,简单修复了这个问题,就是我上面提到的,替换了acme.sh的定时任务。

jeffshead commented 2 years ago

而且,我已经修改了脚本,在这个 9b8d8a2 提交里,简单修复了这个问题,就是我上面提到的,替换了acme.sh的定时任务。

仍然不會自動更新證書。 在三台服務器上失敗。 Still does not auto-renew cert. Failed on three servers.