-
Notifications
You must be signed in to change notification settings - Fork 32
/
acme.sh
358 lines (326 loc) · 15.9 KB
/
acme.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
#!/bin/bash
RED="\033[31m"
GREEN="\033[32m"
YELLOW="\033[33m"
PLAIN='\033[0m'
red(){
echo -e "\033[31m\033[01m$1\033[0m"
}
green(){
echo -e "\033[32m\033[01m$1\033[0m"
}
yellow(){
echo -e "\033[33m\033[01m$1\033[0m"
}
REGEX=("debian" "ubuntu" "centos|red hat|kernel|oracle linux|alma|rocky" "'amazon linux'" "fedora")
RELEASE=("Debian" "Ubuntu" "CentOS" "CentOS" "Fedora")
PACKAGE_UPDATE=("apt-get update" "apt-get update" "yum -y update" "yum -y update" "yum -y update")
PACKAGE_INSTALL=("apt -y install" "apt -y install" "yum -y install" "yum -y install" "yum -y install")
PACKAGE_REMOVE=("apt -y remove" "apt -y remove" "yum -y remove" "yum -y remove" "yum -y remove")
PACKAGE_UNINSTALL=("apt -y autoremove" "apt -y autoremove" "yum -y autoremove" "yum -y autoremove" "yum -y autoremove")
[[ $EUID -ne 0 ]] && red "Note: Please run the script as the root user" && exit 1
CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(hostnamectl 2>/dev/null | grep -i system | cut -d : -f2)" "$(lsb_release -sd 2>/dev/null)" "$(grep -i description /etc/lsb-release 2>/dev/null | cut -d \" -f2)" "$(grep . /etc/redhat-release 2>/dev/null)" "$(grep . /etc/issue 2>/dev/null | cut -d \\ -f1 | sed '/^[ ]*$/d')")
for i in "${CMD[@]}"; do
SYS="$i"
if [[ -n $SYS ]]; then
break
fi
done
for ((int = 0; int < ${#REGEX[@]}; int++)); do
if [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]]; then
SYSTEM="${RELEASE[int]}"
if [[ -n $SYSTEM ]]; then
break
fi
fi
done
[[ -z $SYSTEM ]] && red "Does not support the current OS, please use a supported one" && exit 1
back2menu() {
echo ""
green "The selected command operation execution is completed"
read -rp "Please enter 'Y' to exit, or press the any key back to the main menu:" back2menuInput
case "$back2menuInput" in
y) exit 1 ;;
*) menu ;;
esac
}
install_base(){
if [[ ! $SYSTEM == "CentOS" ]]; then
${PACKAGE_UPDATE[int]}
fi
${PACKAGE_INSTALL[int]} curl wget sudo socat
if [[ $SYSTEM == "CentOS" ]]; then
${PACKAGE_INSTALL[int]} cronie
systemctl start crond
systemctl enable crond
else
${PACKAGE_INSTALL[int]} cron
systemctl start cron
systemctl enable cron
fi
}
install_acme(){
install_base
read -rp "Please enter the registered email (for example: [email protected], or leave empty to automatically generate a fake email): " acmeEmail
if [[ -z $acmeEmail ]]; then
autoEmail=$(date +%s%N | md5sum | cut -c 1-16)
yellow "Skipped entering email, using a fake email address: $acmeEmail"
fi
curl https://get.acme.sh | sh -s email=$acmeEmail
source ~/.bashrc
bash ~/.acme.sh/acme.sh --upgrade --auto-upgrade
bash ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt
if [[ -n $(~/.acme.sh/acme.sh -v 2>/dev/null) ]]; then
green "ACME.SH certificate application script installed successfully!"
else
red "Sorry, the ACME.SH certificate application script installation failed"
green "Suggestions:"
yellow "1. Check the server network connection"
yellow "2. The script could be outdated. Please open up a issue in Github at https://github.com/iprodev/x-ui/issues"
fi
back2menu
}
check_80(){
if [[ -z $(type -P lsof) ]]; then
if [[ ! $SYSTEM == "CentOS" ]]; then
${PACKAGE_UPDATE[int]}
fi
${PACKAGE_INSTALL[int]} lsof
fi
yellow "Checking if the port 80 is in use..."
sleep 1
if [[ $(lsof -i:"80" | grep -i -c "listen") -eq 0 ]]; then
green "Good! Port 80 is not in use"
sleep 1
else
red "Port 80 is currently in use, please close the service this service, which is using port 80:"
lsof -i:"80"
read -rp "If you need to close this service right now, please press Y. Otherwise, press N to abort SSL issuing [Y/N]: " yn
if [[ $yn =~ "Y"|"y" ]]; then
lsof -i:"80" | awk '{print $2}' | grep -v "PID" | xargs kill -9
sleep 1
else
exit 1
fi
fi
}
acme_standalone(){
[[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "Unpacking ACME.SH, Getting ready..." && exit 1
check_80
WARPv4Status=$(curl -s4m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2)
WARPv6Status=$(curl -s6m8 https://www.cloudflare.com/cdn-cgi/trace -k | grep warp | cut -d= -f2)
if [[ $WARPv4Status =~ on|plus ]] || [[ $WARPv6Status =~ on|plus ]]; then
wg-quick down wgcf >/dev/null 2>&1
fi
ipv4=$(curl -s4m8 ip.gs)
ipv6=$(curl -s6m8 ip.gs)
echo ""
yellow "When using port 80 application mode, first point your domain name to your server's public IP address. Otherwise the certificate application will be failed!"
echo ""
if [[ -n $ipv4 && -n $ipv6 ]]; then
echo -e "The public IPv4 address of server is: ${GREEN} $ipv4 ${PLAIN}"
echo -e "The public IPv6 address of server is: ${GREEN} $ipv6 ${PLAIN}"
elif [[ -n $ipv4 && -z $ipv6 ]]; then
echo -e "The public IPv4 address of server is: ${GREEN} $ipv4 ${PLAIN}"
elif [[ -z $ipv4 && -n $ipv6 ]]; then
echo -e "The public IPv6 address of server is: ${GREEN} $ipv6 ${PLAIN}"
fi
echo ""
read -rp "Please enter the pointed domain / sub-domain name: " domain
[[ -z $domain ]] && red "Given domain is invalid. Please use example.com / sub.example.com" && exit 1
green "The given domain name:$domain" && sleep 1
domainIP=$(curl -sm8 ipget.net/?ip="${domain}")
if [[ $domainIP == $ipv6 ]]; then
bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --listen-v6 --insecure
fi
if [[ $domainIP == $ipv4 ]]; then
bash ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 --insecure
fi
if [[ -n $(echo $domainIP | grep nginx) ]]; then
yellow "The domain name analysis failed, please check whether the domain name is correctly entered, and whether the domain name has been pointed to the server's public IP address"
exit 1
elif [[ -n $(echo $domainIP | grep ":") || -n $(echo $domainIP | grep ".") ]]; then
if [[ $domainIP != $ipv4 ]] && [[ $domainIP != $ipv6 ]]; then
if [[ -n $(type -P wg-quick) && -n $(type -P wgcf) ]]; then
wg-quick up wgcf >/dev/null 2>&1
fi
green "Domain name ${domain} Currently pointed IP: ($domainIP)"
red "The current domain name's resolved IP does not match the public IP used of the server"
green "Suggestions:"
yellow "1. Please check whether domain is correctly pointed to the server's current pub;ic IP"
yellow "2. Please make sure that Cloudflare Proxy is closed (only DNS)"
yellow "3. The script could be outdated. Please open up a issue in Github at https://github.com/iprodev/x-ui/issues"
exit 1
fi
fi
bash ~/.acme.sh/acme.sh --install-cert -d ${domain} --key-file /root/private.key --fullchain-file /root/cert.crt --ecc
checktls
}
acme_cfapiTLD(){
[[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "Unpacking ACME.SH, Getting ready..." && exit 1
ipv4=$(curl -s4m8 ip.gs)
ipv6=$(curl -s6m8 ip.gs)
read -rp "Please enter the domain name to issue certificate (sub.example.com): " domain
if [[ $(echo ${domain:0-2}) =~ cf|ga|gq|ml|tk ]]; then
red "Detected a Freenom free domain. Since the Cloudflare API does not support it, it is impossible!"
back2menu
fi
read -rp "Enter CloudFlare Global API Key: " GAK
[[ -z $GAK ]] && red "Unable to verify Cloudflare Global API Key, unable to perform operations!" && exit 1
export CF_Key="$GAK"
read -rp "Enter Cloudflare's registered email: " CFemail
[[ -z $domain ]] && red "Unable to login with the provided email address and API key. Aborted!" && exit 1
export CF_Email="$CFemail"
if [[ -z $ipv4 ]]; then
bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "${domain}" -k ec-256 --listen-v6 --insecure
else
bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "${domain}" -k ec-256 --insecure
fi
bash ~/.acme.sh/acme.sh --install-cert -d "${domain}" --key-file /root/private.key --fullchain-file /root/cert.crt --ecc
checktls
}
acme_cfapiNTLD(){
[[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && red "Unpacking ACME.SH, Getting ready..." && exit 1
ipv4=$(curl -s4m8 ip.gs)
ipv6=$(curl -s6m8 ip.gs)
read -rp "Please enter the main domain name that requires the application certificate (input format: example.com): " domain
[[ -z $domain ]] && red "Given domain is invalid!" && exit 1
if [[ $(echo ${domain:0-2}) =~ cf|ga|gq|ml|tk ]]; then
red "Detected a Freenom free domain. Since the Cloudflare API does not support it, it is impossible!"
back2menu
fi
read -rp "Enter CloudFlare Global API Key: " GAK
[[ -z $GAK ]] && red "Unable to verify Cloudflare Global API Key, unable to perform operations!" && exit 1
export CF_Key="$GAK"
read -rp "Enter CloudFlare registered email: " CFemail
[[ -z $domain ]] && red "Unable to login with the provided email address and API key. Aborted!" && exit 1
export CF_Email="$CFemail"
if [[ -z $ipv4 ]]; then
bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --listen-v6 --insecure
else
bash ~/.acme.sh/acme.sh --issue --dns dns_cf -d "*.${domain}" -d "${domain}" -k ec-256 --insecure
fi
bash ~/.acme.sh/acme.sh --install-cert -d "*.${domain}" --key-file /root/private.key --fullchain-file /root/cert.crt --ecc
checktls
}
checktls() {
if [[ -f /root/cert.crt && -f /root/private.key ]]; then
if [[ -s /root/cert.crt && -s /root/private.key ]]; then
if [[ -n $(type -P wg-quick) && -n $(type -P wgcf) ]]; then
wg-quick up wgcf >/dev/null 2>&1
fi
sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1
echo "0 0 * * * root bash /root/.acme.sh/acme.sh --cron -f >/dev/null 2>&1" >> /etc/crontab
green "Successful application! certificate.crt and Private.key files have been saved to /root/ folder. Use these to your Panel Settings and V2ray configs"
yellow "Certificate.crt file path is as follows : /root/cert.crt"
yellow "Private.key file path is as follows : /root/private.key"
back2menu
else
if [[ -n $(type -P wg-quick) && -n $(type -P wgcf) ]]; then
wg-quick up wgcf >/dev/null 2>&1
fi
red "Sorry. The certificate application failed"
green "Suggestions: "
yellow "1. Check whether the firewall is opened. If the application mode of port 80 is used, please open or release port 80"
yellow "2. Applying for many times in the same domain name may subject it to the risk control of Let'sEncrypt. Please configure another domain that you own or try switching the provider by choosing 9 from the ACME script menu."
yellow "3. Try again with the above used domain after 7 days. "
yellow "4. The script may not be able to keep up with the times, it is recommended to release screenshots to github issues to inquire "
back2menu
fi
fi
}
view_cert(){
[[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "Unpacking ACME.SH. Getting ready..." && exit 1
bash ~/.acme.sh/acme.sh --list
back2menu
}
revoke_cert() {
[[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "Unpacking ACME.SH. Getting ready..." && exit 1
bash ~/.acme.sh/acme.sh --list
read -rp "Please enter the domain name certificate to be revoked (Enter the sub-domain): " domain
[[ -z $domain ]] && red "Invalid domain name and cannot perform operations!" && exit 1
if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then
bash ~/.acme.sh/acme.sh --revoke -d ${domain} --ecc
bash ~/.acme.sh/acme.sh --remove -d ${domain} --ecc
rm -rf ~/.acme.sh/${domain}_ecc
rm -f /root/cert.crt /root/private.key
green "Revoking the domain name certificate of $ {domin} successfully"
back2menu
else
red "No domain name certificate for $ {domain}, please check by yourself!"
back2menu
fi
}
renew_cert() {
[[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "Unpacking ACME.SH. Getting ready..." && exit 1
bash ~/.acme.sh/acme.sh --list
read -rp "Please enter the domain name for the certificate to be renewed (Enter the sub-domain): " domain
[[ -z $domain ]] && red "Unable to enter the domain name and cannot perform operations!" && exit 1
if [[ -n $(bash ~/.acme.sh/acme.sh --list | grep $domain) ]]; then
bash ~/.acme.sh/acme.sh --renew -d ${domain} --force --ecc
checktls
back2menu
else
red "No domain name certificate for $ {domain}, please check the domain name input correctly again"
back2menu
fi
}
switch_provider(){
yellow "Please select the certificate provider, apply for the certificate now to issue from the default provider "
yellow "If the certificate application fails, for example, if there are too many applications requested from LetSencrypt.org within a day, you can choose Buypass.com or Zerossl.com to apply."
echo -e " ${GREEN}1.${PLAIN} Letsencrypt.org"
echo -e " ${GREEN}2.${PLAIN} BuyPass.com"
echo -e " ${GREEN}3.${PLAIN} ZeroSSL.com"
read -rp "Please select certificate provider [1-3]: " provider
case $provider in
2) bash ~/.acme.sh/acme.sh --set-default-ca --server buypass && green "Switched certificate provider to BuyPass.com!" ;;
3) bash ~/.acme.sh/acme.sh --set-default-ca --server zerossl && green "Switched certificate provider to ZeroSSL.com!" ;;
*) bash ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt && green "Switched certificate provider to Letsencrypt.org!" ;;
esac
back2menu
}
uninstall() {
[[ -z $(~/.acme.sh/acme.sh -v 2>/dev/null) ]] && yellow "Unpacking ACME.SH. Getting ready...!" && exit 1
~/.acme.sh/acme.sh --uninstall
sed -i '/--cron/d' /etc/crontab >/dev/null 2>&1
rm -rf ~/.acme.sh
green "Acme One-click application certificate script has been completely uninstalled. Bye Bye!"
}
menu() {
clear
echo "--------------------------------------------------------------"
echo -e "____ ____ _ _ ____ ____ ____ ____ _ _ _ _ _ "
echo -e "|__| | |\/| |___ |___ | | |__/ \/ __ | | | "
echo -e "| | |___ | | |___ | |__| | \ _/\_ |__| | "
echo "--------------------------------------------------------------"
echo ""
echo -e " ${GREEN}1.${PLAIN} Install ACME.SH"
echo -e " ${GREEN}2.${PLAIN} ${RED}Uninstall ACME.SH${PLAIN}"
echo " -------------"
echo -e " ${GREEN}3.${PLAIN} Certificate issuing via DNS API - Recommended ${YELLOW}(Port 80 should be open)${PLAIN}"
echo -e " ${GREEN}4.${PLAIN} Certificate issuing via Cloudflare API for root-domain${GREEN}${PLAIN} ${RED}(Not working for Freenom free domains)${PLAIN}"
echo -e " ${GREEN}5.${PLAIN} Certificate issuing via Cloudflare API for sub-domain ${PLAIN}$ ${RED}(Not working for Freenom free domains)${PLAIN}"
echo " -------------"
echo -e " ${GREEN}6.${PLAIN} Check the certificate"
echo -e " ${GREEN}7.${PLAIN} Revoke the certificate"
echo -e " ${GREEN}8.${PLAIN} Manual renewal of certificate"
echo -e " ${GREEN}9.${PLAIN} Switch certificate issuer"
echo " -------------"
echo -e " ${GREEN}0.${PLAIN} Exit script"
echo ""
read -rp "Please enter the option [0-9]: " NumberInput
case "$NumberInput" in
1) install_acme ;;
2) uninstall ;;
3) acme_standalone ;;
4) acme_cfapiTLD ;;
5) acme_cfapiNTLD ;;
6) view_cert ;;
7) revoke_cert ;;
8) renew_cert ;;
9) switch_provider ;;
*) exit 1 ;;
esac
}
menu