-
Notifications
You must be signed in to change notification settings - Fork 70
/
onekey-tailscale.sh
439 lines (420 loc) · 15.5 KB
/
onekey-tailscale.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
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
#!/bin/bash
end="\033[0m"
black="\033[0;30m"
blackb="\033[1;30m"
white="\033[0;37m"
whiteb="\033[1;37m"
red="\033[0;31m"
redb="\033[1;31m"
green="\033[0;32m"
greenb="\033[1;32m"
yellow="\033[0;33m"
yellowb="\033[1;33m"
blue="\033[0;34m"
blueb="\033[1;34m"
purple="\033[0;35m"
purpleb="\033[1;35m"
lightblue="\033[0;36m"
lightblueb="\033[1;36m"
checkCPU(){
CPUArch=$(uname -m)
if [[ "$CPUArch" == "aarch64" ]];then
arch=linux-arm64
elif [[ "$CPUArch" == "x86_64" ]];then
arch=linux-amd64
else
echo -e "${red}不支持当前系统,程序退出···${end}"
exit 0
fi
}
checkCPU
check_dependencies(){
os_detail=$(cat /etc/os-release 2> /dev/null)
if_debian=$(echo $os_detail | grep 'ebian')
if_redhat=$(echo $os_detail | grep 'rhel')
if [ -n "$if_debian" ];then
InstallMethod="apt-get"
elif [ -n "$if_redhat" ] && [[ "$os_version" -lt 8 ]];then
InstallMethod="yum"
elif [[ "$os_version" == "MacOS" ]];then
InstallMethod="brew"
fi
}
check_dependencies
$InstallMethod install lsof -y >/dev/null
install_tailscale(){
curl -fsSL https://tailscale.com/install.sh | sh
echo -e "${yellow}开始配置机器IP转发${end}"
echo 'net.ipv4.ip_forward = 1' | tee -a /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' | tee -a /etc/sysctl.conf
sysctl -p /etc/sysctl.conf
echo -n -e "${yellow}请输入你当前机器的IP网段,注意最后一位填写0,比如192.168.2.0,请输入:${end}"
read ipduan
tailscale up --advertise-routes=${ipduan}/24 --accept-routes
echo -e "${green}tailscale客户端部署完毕,如需要打通该设备所处网段其他设备的访问,请进入tailscale官网打开这台设备的转发开关,${end}${red}菜单名称:Edit route settings ${end},${green}链接:https://login.tailscale.com/admin/machines ${end}"
}
install_go(){
goweb="https://studygolang.com"
# goweb="https://golang.google.cn"
if [[ $arch == "linux-amd64" ]]; then
gourl=$(curl -s https://studygolang.com/dl | sed -n '/dl\/golang\/go.*\.linux-amd64\.tar\.gz/p' | sed -n '1p' | sed -n '/1/p' | grep -oP 'href="\K[^"]*(?=")')
# gourl=`curl -s https://golang.google.cn/dl/ | sed -n '/dl\/go.*\.linux-amd64\.tar\.gz/p'| sed -n '1p' | sed -n '/1/p' | awk 'BEGIN{FS="\""}{print $4}'`
elif [[ $arch == "linux-arm64" ]]; then
gourl=$(curl -s https://studygolang.com/dl | sed -n '/dl\/golang\/go.*\.linux-arm64\.tar\.gz/p' | sed -n '1p' | sed -n '/1/p' | grep -oP 'href="\K[^"]*(?=")')
# gourl=`curl -s https://golang.google.cn/dl/ | sed -n '/dl\/go.*\.linux-arm64\.tar\.gz/p'| sed -n '1p' | sed -n '/1/p' | awk 'BEGIN{FS="\""}{print $6}'`
fi
wget ${goweb}${gourl} -O go.tar.gz
tar -C /usr/local -xzf go.tar.gz
echo -e "export GOROOT=/usr/local/go\nexport GOPATH=/root/goProject\nexport GOBIN=\$GOPATH/bin\nexport PATH=\$PATH:\$GOROOT/bin\nexport PATH=\$PATH:\$GOPATH/bin" >>/etc/profile
echo -e "${yellow}Go环境部署完毕,请退出SSH窗口重进一次使变量生效。${end}"
exit 0
}
install_derper(){
if [[ $(which go) == "" ]]; then
echo -e "${red}检测发现系统未部署Go环境,开始部署Go环境${end}"
install_go
else
go install tailscale.com/cmd/derper@main
if [[ $(which derper) == "" ]]; then
echo -e "${red}derper安装失败,程序退出${end}"
exit 0
fi
fi
echo -e "${yellow}因为tailscale中继服务器需要配合域名和域名证书,请根据命令行提示操作${end}"
echo "=======================Let's Encrypt环境准备======================================="
if command -v python > /dev/null 2>&1; then
echo 'python 环境就绪...'
python_command=python
else
echo 'python环境不存在,即将开始自动安装。。'
apt-get -y install python || yum -y install python
echo 'python 安装成功'
python_command=python
fi
if command -v openssl > /dev/null 2>&1; then
echo 'openssl 环境就绪...'
else
echo 'openssl 不存在,准备安装。。。'
apt-get -y install openssl || yum -y install openssl
fi
if command -v nginx> /dev/null 2>&1; then
echo 'nginx 环境就绪...'
else
echo "nginx 环境不存在,是否需要自动安装?"
echo -e '\n'
cat << EOF
是否需要安装(y/n)?
EOF
read -p "> " confirm
if [[ $confirm == "y" ]]; then
apt-get -y install nginx || yum -y install nginx
echo 'nginx 环境安装成功'
else
exit 0
fi
fi
echo "==========================环境准备完成==========================="
echo "开始配置"
echo "1、域名配置,请确保你的域名已解析到本机"
echo "请输入域名(多个请用空格隔开):按回车结束(例:www.baidu.com)"
read -p "> " web_domains
domain_length=0
sign_domain_str=''
web_first_domain=$(echo $web_domains|tr -s [:blank:]|cut -d ' ' -f 1)
nginx_web_config_file=$web_first_domain".conf"
for web_domain in ${web_domains[@]}
do
sign_domain_str=$sign_domain_str"DNS:"$web_domain","
domain_length=$(($domain_length+1))
done
sign_domain_str=${sign_domain_str:0:${#sign_domain_str}-1}
echo "$sign_domain_str"
echo "2、站点绝对路径配置,如果未输入或者输入非绝对路径,就默认使用域名为目录配置到/tmp目录下"
mkdir -p /certs
read -p "> " web_dir
if [[ -z "$web_dir" || ! "$web_dir" == /* ]]; then
web_dir="/certs/"$web_first_domain
fi
echo "3、nginx路径配置,如果你的默认路径是/etc/nginx,请直接回车"
read -p "> " nginx_config_dir
if [[ -z "$nginx_config_dir" ]]; then
nginx_config_dir=/etc/nginx
fi
echo -e "\n"
cat << EOF
确认配置
网站根目录: $web_dir
域名: $web_domains
nginx配置文件路径: $nginx_config_dir
请输入1或2
1):确认
2):退出
EOF
read -p "> " confirm
if [[ $confirm -eq 2 ]]; then
exit 0
fi
echo "===========================自动化配置开始================================="
mkdir -p ${web_dir}"/certificate/challenges"
chmod -R 755 ${web_dir}"/certificate"
web_first_parent_dir="/"$(echo $web_dir|cut -d "/" -f2)
find $web_first_parent_dir -type d -exec chmod o+x {} \;
cd $web_dir"/certificate"
echo "Create a Let's Encrypt account private key"
openssl genrsa 4096 > account.key
echo "generate a domain private key"
openssl genrsa 4096 > domain.key
if [[ $domain_length -gt 1 ]]; then
openssl req -new -sha256 -key domain.key -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=$sign_domain_str")) > domain.csr || openssl req -new -sha256 -key domain.key -subj "/" -reqexts SAN -config <(cat /etc/pki/tls/openssl.cnf <(printf "[SAN]\nsubjectAltName=$sign_domain_str")) > domain.csr
else
openssl req -new -sha256 -key domain.key -subj "/CN=$web_domains" > domain.csr
fi
cat > $nginx_config_dir"/conf.d/"$nginx_web_config_file <<EOF
server {
listen 80;
server_name $web_domains;
location /.well-known/acme-challenge/ {
alias $web_dir/certificate/challenges/;
try_files \$uri =404;
}
}
EOF
service nginx restart
wget --no-check-certificate https://cdn.jsdelivr.net/gh/diafygi/acme-tiny@master/acme_tiny.py
$python_command acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir $web_dir/certificate/challenges > ./signed.crt || exiterr "create the http website failed,please view the issue of github doc"
#NOTE: For nginx, you need to append the Let's Encrypt intermediate cert to your cert
wget --no-check-certificate https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem -O intermediate.pem
cat signed.crt intermediate.pem > chained.pem
cp chained.pem $web_domains.crt
cp domain.key $web_domains.key
cat > $nginx_config_dir"/conf.d/"$nginx_web_config_file <<EOF
server {
listen 80;
server_name $web_domains;
rewrite ^(.*) https://\$host\$1 permanent;
}
server {
listen 443;
server_name $web_domains;
root $web_dir;
index index.html index.htm index.php;
ssl on;
ssl_certificate $web_dir/certificate/chained.pem;
ssl_certificate_key $web_dir/certificate/domain.key;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
ssl_session_cache shared:SSL:50m;
ssl_prefer_server_ciphers on;
location /.well-known/acme-challenge/ {
alias $web_dir/certificate/challenges/;
try_files \$uri =404;
}
location /download {
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
}
#如果是配置代理请放开以下注释即可
#location / {
#proxy_pass http://120.80.99.120:20000/;
#proxy_redirect off;
#proxy_hide_header Vary;
#proxy_set_header Accept-Encoding '';
#proxy_set_header Host $host;
#proxy_set_header Referer $http_referer;
#proxy_set_header Cookie $http_cookie;
#proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#}
}
EOF
if [[ ! -f $web_dir/index.html ]]; then
cat > $web_dir/index.html << EOF
generate https website succssfully<br/>
this is the index.html of $web_first_domain <br/>
yout can visit this page from $web_domains
EOF
fi
# current_user=$USER
# current_user=$(id -un) not work for sudo
current_user=$(who am i|awk '{print $1}')
current_user_group=$(id -gn $current_user)
chown -R $current_user:$current_user_group $web_dir
chown $current_user:$current_user_group $nginx_config_dir"/conf.d/"$nginx_web_config_file
chmod -R 755 $web_dir
service nginx restart
echo -e "\n\n"
cat << EOF
generate https website succssfully
your website directory is $web_dir
your nginx config file is $nginx_config_dir/conf.d/$nginx_web_config_file
you can visit your website through these domains
EOF
for web_domain in ${web_domains[@]}
do
echo https://$web_domain
done
cat > $web_dir/certificate/renew_cert.bash <<EOF
cd $web_dir/certificate
wget --no-check-certificate https://cdn.jsdelivr.net/gh/diafygi/acme-tiny@master/acme_tiny.py -O acme_tiny.py
$python_command ./acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir $web_dir/certificate/challenges/ > /tmp/signed.crt || exit
wget --no-check-certificate -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > intermediate.pem
cat /tmp/signed.crt intermediate.pem > $web_dir/certificate/chained.pem
cat /tmp/signed.crt intermediate.pem > $web_dir/certificate/chained.pem
cp $web_dir/certificate/domain.key $web_dir/certificate/$web_domains.key
cp $web_dir/certificate/chained.pem $web_dir/certificate/$web_domains.crt
service nginx reload
EOF
echo "Let's Encrypt 证书有效期定时任务配置"
if command -v crontab > /dev/null 2>&1; then
echo 'crontab 已安装'
else
echo 'crontab 未安装,将为您自动安装...'
apt-get -y install cron || yum -y install cron
fi
echo "1 1 1 * * root bash $web_dir/certificate/renew_cert.bash >> /var/log/renew_cert_error.log 2 >> /var/log/renew_cert.log" >> /etc/crontab
echo "证书续期定时器添加成功"
if [[ $(lsof -i:443) != "" ]];then
echo -n -e "${red}检测发现443端口已经被占用,derper默认占用443端口,请输入自定义的tls端口号:${end}"
read port
echo -e "${yellow}开始部署derper进程值守···${end}"
cat > /etc/systemd/system/derper.service <<EOF
Description=derper
After=network.target
[Service]
Type=simple
ExecStart=/root/goProject/bin/derper -hostname $web_domains -c=derper.conf -a :$port -http-port -1 -certdir $web_dir/certificate -certmode manual -stun
ExecStop=/usr/bin/kill -9 \$(ps aux |grep derper|awk '{print $2}'|head -1)
Restart=on-abort
User=root
[Install]
WantedBy=default.target
EOF
systemctl enable derper
systemctl daemon-reload
systemctl start derper
echo -e "${green}部署derper进程值守完成,后续可通过systemctl stop derper 和systemctl start derper 命令来关闭和启动derper服务···${end}"
echo -e "${lightblueb}登陆tailscale官网,用如下代码进行替换tailscale官网中的Access Controls配置${end}"
cat << EOF
// Example/default ACLs for unrestricted connections.
{
// Declare static groups of users beyond those in the identity service.
"groups": {
"group:example": [ "[email protected]", "[email protected]" ],
},
// Declare convenient hostname aliases to use in place of IP addresses.
"hosts": {
"example-host-1": "100.100.100.100",
},
// Access control lists.
"acls": [
// Match absolutely everything. Comment out this section if you want
// to define specific ACL restrictions.
{ "action": "accept", "users": ["*"], "ports": ["*:*"] },
],
"derpMap": {
"OmitDefaultRegions": true,
"Regions": { "900": {
"RegionID": 900,
"RegionCode": "myderp",
"Nodes": [{
"Name": "1",
"RegionID": 900,
"HostName":"$web_domains",
"DERPPort": $port
}]
}}
}
}
EOF
else
echo -e "${yellow}开始部署derper进程值守···${end}"
cat > /etc/systemd/system/derper.service <<EOF
Description=derper
After=network.target
[Service]
Type=simple
ExecStart=/root/goProject/bin/derper -hostname $web_domains -c=derper.conf -a :443 -http-port -1 -certdir $web_dir/certificate -certmode manual -stun
ExecStop=/usr/bin/kill -9 \$(ps aux |grep derper|awk '{print $2}'|head -1)
Restart=on-abort
User=root
[Install]
WantedBy=default.target
EOF
systemctl enable derper
systemctl daemon-reload
systemctl start derper
echo -e "${green}部署derper进程值守完成,后续可通过systemctl stop derper 和systemctl start derper 命令来关闭和启动derper服务···${end}"
echo -e "${lightblueb}登陆tailscale官网,用如下代码进行替换tailscale官网中的Access Controls配置${end}"
cat << EOF
// Example/default ACLs for unrestricted connections.
{
// Declare static groups of users beyond those in the identity service.
"groups": {
"group:example": [ "[email protected]", "[email protected]" ],
},
// Declare convenient hostname aliases to use in place of IP addresses.
"hosts": {
"example-host-1": "100.100.100.100",
},
// Access control lists.
"acls": [
// Match absolutely everything. Comment out this section if you want
// to define specific ACL restrictions.
{ "action": "accept", "users": ["*"], "ports": ["*:*"] },
],
"derpMap": {
"OmitDefaultRegions": true,
"Regions": { "900": {
"RegionID": 900,
"RegionCode": "myderp",
"Nodes": [{
"Name": "1",
"RegionID": 900,
"HostName":"$web_domains",
"DERPPort": 443
}]
}}
}
}
EOF
fi
}
copyright(){
echo -e "
${green}###########################################################${end}
${green}# #${end}
${green}# Tailscale一键部署脚本 #${end}
${green}# Powered by 翔翎 #${end}
${green}# #${end}
${green}###########################################################${end}"
}
menu() {
echo -e "
${red}0.${end} 退出脚本
${green}———————————————————————————————————————————————————————————${end}
${green}1.${end} 一键部署Tailscale私有中继服务器
${green}2.${end} 一键部署Tailscale客户端服务
"
read -p "请输入数字 :" num
case "$num" in
0)
exit 0
;;
1)
install_derper
;;
2)
install_tailscale
;;
*)
clear
echo -e "${red}出现错误:请输入正确数字 [0-2]${end}"
sleep 3s
copyright
menu
;;
esac
}
copyright
menu