Last active
March 31, 2025 20:49
-
-
Save whg517/54f93ac2ce441bc3fb09d40b6e34afaf to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -ex | |
# 相关技术连接: | |
# https://github.com/XTLS/Xray-install | |
# https://github.com/XTLS/Xray-examples | |
## !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
## !不建议关闭操作系统的防火墙,除非你在服务商中配置了防火墙! | |
## !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
## 脚本说明: | |
## - Caddy: 服务器安装 Caddy Web 服务,并使用 Caddy 的自动 TLS 功能,自动生成本地私有证书,同时自动轮转新证书,这些都是由 Caddy 自动完成 | |
## 如果有域名,Caddy 会自动生成和更新免费证书。使用 Caddy 同时提供 Web 服务功能,用来伪装访问地址。 | |
## - 使用 https://github.com/PanJiaChen/vue-element-admin.git 构建的项目作为 Web 服务项目。当使用浏览器打开地址,访问的是一个页面。 | |
## - 使用 https://github.com/XTLS/Xray-install 的 XTLS 强大回落功能让代理同时支持 XTLS ,VLESS 和 VMESS 多种协议。 | |
## - 启用 BBR 加速 | |
## 注意: | |
## Caddy 只为 443 端口启用自动 TLS 证书生成。所以 XTLS 不能占用 443 端口,可以选择了常见的 8443 端口,同时回落到 80 端口。 | |
## 脚本暂未在生产环境中测试。请谨慎使用一键执行,建议逐步执行。 | |
## 脚本不提供清理功能,如果需要清理,请手动删除相关文件和服务。 | |
## 清理过程: | |
## - 停止并删除 xray 服务 | |
## - 使用 systemd 命令停止 xray 服务 | |
## - 删除 /etc/systemd/system 目录中关于 xray 的文件 | |
## - 删除 /usr/local/etc/xray 目录 | |
## - 删除 /etc/firewalld/services/xray.xml 文件 | |
## - 停止并删除 caddy 服务 | |
## - 使用 systemd 命令停止 caddy 服务 | |
## - 删除 /etc/systemd/system 目录中关于 caddy 的文件 | |
## - 删除 /etc/caddy 目录 | |
## - 删除 /var/log/caddy 目录 | |
## - 删除 /opt/wwwroot/ 目录 | |
## - 删除 /etc/firewalld/services/caddy.xml 文件 | |
## - 使用 find 命令查找 caddy 和 xray 关键词,删除相关文件 | |
###################################################################################################### | |
## 安装前配置 | |
###################################################################################################### | |
# 打开注释,填写你的域名,如果没有请忽略 | |
# DOMAIN=example.com | |
## Xray VLESS 端口,默认为 28443 ,如果需要更改请修改 | |
## 这里选择 28443 高位端口,增大安全性。 | |
## Xray LESS 具备协议回落,当前配置支持会落到 trojan、vlessws、vmessws。 | |
## 如果这些都无法满足,则返回伪装的 Web 服务。 | |
VLESS_PORT=28443 | |
TROJAN_PORT=1310 | |
VLESS_WS_PORT=3456 | |
VMESS_WS_PORT=1234 | |
## Enable system firewall, default is true. | |
## If you have configured the firewall in the cloud provider, you can set it to false. | |
ENABLE_FIREWALL=true | |
###################################################################################################### | |
## 脚本逻辑,不建议修改,如果不懂可以忽略,直接执行脚本 | |
###################################################################################################### | |
# Main function | |
# Arguments: | |
# None | |
# Returns: | |
# None | |
function main() { | |
initGlobalVariable | |
initSystemEnvironment | |
installWebServer | |
deployWebApp | |
installXray | |
} | |
# Initialize global variables, the upper case variables are global variables, | |
# which can be used in any function | |
# Arguments: | |
# None | |
# Returns: | |
# None | |
function initGlobalVariable() { | |
if [ -z "${DOMAIN}" ]; then | |
DOMAIN=$(curl -s https://httpbin.org/ip | grep -oP '"origin": "\K(.*)(?=")') | |
fi | |
WEB_ROOT=/opt/wwwroot/xray | |
CADDY_LOG=/var/log/caddy | |
echo "INFO: Configuration detail:" >&2 | |
echo "INFO: DOMAIN: ${DOMAIN}" >&2 | |
echo "INFO: WEB_ROOT: ${WEB_ROOT}" >&2 | |
echo "INFO: CADDY_LOG: ${CADDY_LOG}" >&2 | |
echo "INFO: VLESS_PORT: ${VLESS_PORT}" >&2 | |
echo "INFO: TROJAN_PORT: ${TROJAN_PORT}" >&2 | |
echo "INFO: VLESS_WS_PORT: ${VLESS_WS_PORT}" >&2 | |
echo "INFO: VMESS_WS_PORT: ${VMESS_WS_PORT}" >&2 | |
echo "" >&2 | |
} | |
# Initialize the system environment, | |
# including: | |
# - Close SELINUX | |
# - Install system software | |
# - Configure system parameters | |
# Arguments: | |
# None | |
# Returns: | |
# None | |
function initSystemEnvironment(){ | |
echo "INFO: Close SELINUX" >&2 | |
sed -i 's/\(^SELINUX=\).*$/\1disabled/' /etc/selinux/config | |
setenforce 0 > /dev/null 2>&1 || true | |
echo "INFO: Update system software" >&2 | |
dnf -y update | |
dnf -y install git vim tar | |
echo "INFO: Configure system parameters" >&2 | |
echo '' | |
echo '# 20240620 ' >> /etc/sysctl.conf | |
echo 'vm.swappiness = 10' >> /etc/sysctl.conf | |
echo '' | |
echo 'net.ipv4.tcp_syncookies = 1' >> /etc/sysctl.conf | |
echo 'net.ipv4.tcp_timestamps = 1' >> /etc/sysctl.conf | |
echo 'net.ipv4.tcp_tw_reuse = 1 ' >> /etc/sysctl.conf | |
echo 'net.ipv4.ip_local_port_range = 1024 65535' >> /etc/sysctl.conf | |
echo 'net.ipv4.tcp_max_syn_backlog = 1024' >> /etc/sysctl.conf | |
echo '' | |
echo 'vm.overcommit_memory = 1' >> /etc/sysctl.conf | |
echo '' | |
echo 'fs.inotify.max_user_instances = 4096' >> /etc/sysctl.conf | |
echo '' | |
echo 'fs.file-max = 65535' >> /etc/sysctl.conf | |
echo '' | |
echo '# 20240620' >> /etc/security/limits.conf | |
echo '* soft nofile 65535' >> /etc/security/limits.conf | |
echo '* hard nofile 65535' >> /etc/security/limits.conf | |
echo '* soft nproc 65535' >> /etc/security/limits.conf | |
echo '* hard nproc 65535' >> /etc/security/limits.conf | |
echo 'root soft nofile 65535' >> /etc/security/limits.conf | |
echo 'root hard nofile 65535' >> /etc/security/limits.conf | |
echo 'root soft nproc 65535' >> /etc/security/limits.conf | |
echo 'root hard nproc 65535' >> /etc/security/limits.conf | |
/sbin/sysctl -p | |
} | |
# Install Caddy Web server, and configure the firewall to open http 80 and https 443 ports | |
# Arguments: | |
# None | |
# Returns: | |
# None | |
function installWebServer() { | |
echo "INFO: Install Caddy Web server" >&2 | |
dnf -y install 'dnf-command(copr)' | |
dnf -y copr enable @caddy/caddy | |
dnf -y install caddy | |
systemctl enable caddy | |
systemctl start caddy | |
curl http://localhost | |
# Trust the Caddy certificate | |
caddy trust | |
if [ ${ENABLE_FIREWALL} = true ]; then | |
echo "INFO: Enable Caddy firewall rules" >&2 | |
configureWebFirewall | |
fi | |
} | |
# Configure the firewall to open the http 80 and https 443 ports | |
# Arguments: | |
# None | |
# Returns: | |
# None | |
function configureWebFirewall() { | |
firewall-cmd --add-service=http --permanent | |
firewall-cmd --add-service=https --permanent | |
firewall-cmd --reload | |
} | |
# Deploy sample Web app, and configure Caddy to use the Web app. | |
# Use vue-element-admin source code to build a web app. It disguise for xray service. | |
# If a FQDN domain is configured, Caddy will automatically generate a public certificate, | |
# and automatically rotate the certificate. | |
# So we can securely access the xray service , and protocol our data to xray. | |
# Arguments: | |
# None | |
# Returns: | |
# None | |
function deployWebApp() { | |
if [ ! -d "${WEB_ROOT}" ]; then | |
mkdir -p ${WEB_ROOT} | |
chown -R caddy:caddy ${WEB_ROOT} | |
fi | |
if [ ! -d "${CADDY_LOG}" ]; then | |
mkdir -p ${CADDY_LOG} | |
chown -R caddy:caddy ${CADDY_LOG} | |
fi | |
if [ ! -d "/opt/devtools" ]; then | |
mkdir -p /opt/devtools | |
fi | |
curl -o /tmp/node-v18.16.0-linux-x64.tar.xz -C - https://nodejs.org/dist/v18.16.0/node-v18.16.0-linux-x64.tar.xz | |
if [ -d "/opt/devtools/node-v18.16.0" ]; then | |
mv /opt/devtools/node-v18.16.0 /opt/devtools/node-v18.16.0_bak$(date +%Y%m%d%H%M%S) | |
fi | |
tar -xvf /tmp/node-v18.16.0-linux-x64.tar.xz -C /tmp | |
mv /tmp/node-v18.16.0-linux-x64 /opt/devtools/node-v18.16.0 | |
export NODE_PATH=/opt/devtools/node-v18.16.0/ | |
export PATH=$NODE_PATH/bin:$PATH | |
node -v | |
local web_app_src="/tmp/vue-element-admin" | |
if [ -d "$web_app_src" ]; then | |
rm -rf "$web_app_src" | |
fi | |
git clone https://github.com/PanJiaChen/vue-element-admin.git | |
# https://stackoverflow.com/questions/69692842/error-message-error0308010cdigital-envelope-routinesunsupported | |
export NODE_OPTIONS=--openssl-legacy-provider | |
cd vue-element-admin | |
npm install | |
npm run build:prod | |
cp -R dist/* ${WEB_ROOT} | |
chown -R caddy:caddy ${WEB_ROOT} | |
cat > /etc/caddy/Caddyfile <<EOF | |
${DOMAIN} { | |
root * ${WEB_ROOT} | |
file_server | |
log { | |
output file ${CADDY_LOG}/access.log { | |
roll_size 100mb | |
roll_keep 5 | |
roll_keep_for 15d | |
} | |
} | |
} | |
EOF | |
systemctl restart caddy | |
curl -k -I https://${DOMAIN} | |
} | |
# Install xray and configure xray to use caddy generated certificate. | |
# After installation, xray firewall rules will be created, and caddy firewall will be opened. | |
# Arguments: | |
# None | |
# Returns: | |
# None | |
function installXray() { | |
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install | |
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install-geodata | |
# 使用 caddy 用户启动 xray 服务。主要是因为 caddy 自动生成的证书只有 caddy 用户才有权限读取。 | |
# xray 默认使用的是 nobody 用户,在启动时无法读取 caddy 证书导致启动失败 | |
sed -i 's/\(^User=\).*$/\1caddy/' /etc/systemd/system/xray.service | |
systemctl daemon-reload | |
CADDY_TRUST_PATH="/var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory" | |
local certificate_file="${CADDY_TRUST_PATH}/${DOMAIN}/${DOMAIN}.crt" | |
local key_file="${CADDY_TRUST_PATH}/${DOMAIN}/${DOMAIN}.key" | |
cat > /usr/local/etc/xray/config.json <<EOF | |
{ | |
"log": { | |
"loglevel": "warning" | |
// "loglevel": "debug" | |
}, | |
"dns": { | |
"hosts": { | |
// "baidu.com": "127.0.0.1", | |
"dns.google": [ | |
"8.8.8.8", | |
"8.8.4.4" | |
] | |
}, | |
"servers": [ | |
"1.1.1.1", | |
"8.8.8.8", | |
"8.8.4.4", | |
{ | |
"address": "1.2.3.4", | |
"port": 5353, | |
"domains": [ | |
"domain:xray.com" | |
], | |
"expectIPs": [ | |
"geoip:cn" | |
], | |
"skipFallback": false, | |
"clientIP": "1.2.3.4" | |
}, | |
{ | |
"address": "https://8.8.8.8/dns-query", | |
"domains": [ | |
"geosite:netflix" | |
], | |
"skipFallback": true, | |
"queryStrategy": "UseIPv4" | |
}, | |
{ | |
"address": "https://1.1.1.1/dns-query", | |
"domains": [ | |
"geosite:openai" | |
], | |
"skipFallback": true, | |
"queryStrategy": "UseIPv6" | |
}, | |
"localhost" | |
], | |
"clientIp": "1.2.3.4", | |
"queryStrategy": "UseIP", | |
"disableCache": false, | |
"disableFallback": false, | |
"disableFallbackIfMatch": false, | |
"tag": "dns_inbound" | |
}, | |
"inbounds": [ | |
{ | |
"port": "${VLESS_PORT}", | |
"protocol": "vless", | |
"tag": "vless", | |
"settings": { | |
"clients": [ | |
{ | |
"id": "$(uuidgen)", // use uuidgen to generate a unique ID | |
"flow": "xtls-rprx-vision", | |
"level": 0, | |
"email": "[email protected]" | |
} | |
], | |
"decryption": "none", | |
"fallbacks": [ | |
{ | |
"dest": ${TROJAN_PORT}, // Fall back to Xray's Trojan protocol by default | |
"xver": 1 | |
}, | |
{ | |
"path": "/websocket", // Must be replaced with a custom PATH | |
"dest": ${VLESS_WS_PORT}, | |
"xver": 1 | |
}, | |
{ | |
"path": "/vmessws", // Must be replaced with a custom PATH | |
"dest": ${VMESS_WS_PORT}, | |
"xver": 1 | |
}, | |
{ | |
"dest": 80 // or fall back to other proxies that are also probing-proof | |
} | |
] | |
}, | |
"streamSettings": { | |
"network": "tcp", | |
"security": "tls", | |
"tlsSettings": { | |
"serverName": "${DOMAIN}", | |
"rejectUnknownSni": true, | |
"allowInsecure": false, | |
"alpn": [ | |
"h2", | |
"http/1.1" | |
], | |
"minVersion": "1.2", | |
"certificates": [ | |
{ | |
"certificateFile": "${certificate_file}", // Replace with your certificate, absolute path | |
"keyFile": "${key_file}" // Replace it with your private key, absolute path | |
} | |
] | |
} | |
}, | |
"sniffing": { | |
"enabled": true, | |
"destOverride": [ | |
"http", | |
"tls" | |
] | |
} | |
}, | |
{ | |
"port": ${TROJAN_PORT}, | |
"listen": "127.0.0.1", | |
"protocol": "trojan", | |
"settings": { | |
"clients": [ | |
{ | |
"password": "$(uuidgen)", | |
"level": 0, | |
"email": "[email protected]" | |
} | |
], | |
"fallbacks": [ | |
{ | |
"dest": 80 | |
} | |
] | |
}, | |
"streamSettings": { | |
"network": "tcp", | |
"security": "none", | |
"tcpSettings": { | |
"acceptProxyProtocol": true | |
} | |
} | |
}, | |
{ | |
"port": ${VLESS_WS_PORT}, | |
"listen": "127.0.0.1", | |
"protocol": "vless", | |
"tag": "vlessws", | |
"settings": { | |
"clients": [ | |
{ | |
"id": "$(uuidgen)", | |
"level": 0, | |
"email": "[email protected]" | |
} | |
], | |
"decryption": "none" | |
}, | |
"streamSettings": { | |
"network": "ws", | |
"security": "none", | |
"wsSettings": { | |
"acceptProxyProtocol": true, // Reminder: If you use Nginx/Caddy to reverse generation WS, you need to delete this line | |
"path": "/websocket", // It must be replaced with a custom PATH, which needs to be consistent with the shunt | |
"headers": { | |
"Host": "${DOMAIN}" | |
} | |
} | |
} | |
}, | |
{ | |
"port": ${VMESS_WS_PORT}, | |
"listen": "127.0.0.1", | |
"protocol": "vmess", | |
"tag": "vmessws", | |
"settings": { | |
"clients": [ | |
{ | |
"id": "$(uuidgen)", | |
"level": 0, | |
"email": "[email protected]" | |
} | |
] | |
}, | |
"streamSettings": { | |
"network": "ws", | |
"security": "none", | |
"wsSettings": { | |
"acceptProxyProtocol": true, // Reminder: If you use Nginx/Caddy to reverse generation WS, you need to delete this line | |
"path": "/vmessws", // It must be replaced with a custom PATH, which needs to be consistent with the shunt | |
"headers": { | |
"Host": "${DOMAIN}" | |
} | |
} | |
} | |
} | |
], | |
"outbounds": [ | |
{ | |
"protocol": "freedom", | |
"tag": "direct" | |
}, | |
{ | |
"protocol": "blackhole", | |
"tag": "block" | |
} | |
], | |
"routing": { | |
"domainStrategy": "IPIfNonMatch", | |
"domainMatcher": "hybrid", | |
"rules": [ | |
{ | |
"domainMatcher": "hybrid", | |
"domains": [ | |
"geosite:category-ads-all" | |
], | |
"outboundTag": "block" | |
} | |
] | |
}, | |
"policy": { | |
"levels": { | |
"0": { | |
"handshake": 2, // The handshake time limit when the connection is established, in seconds, the default value is 4, it is recommended to be different from the default value | |
"connIdle": 120 // Connection idle time limit in seconds, the default value is 300, it is recommended to be different from the default value | |
} | |
} | |
} | |
} | |
EOF | |
systemctl restart xray | |
if [ ${ENABLE_FIREWALL} = true ]; then | |
echo "INFO: Enable xray firewall rules" >&2 | |
configureXrayFirewalld | |
fi | |
} | |
# Configure the firewall to open the xray port | |
# Arguments: | |
# None | |
# Returns: | |
# None | |
function configureXrayFirewalld() { | |
# Create xray firewall rules | |
cat > /etc/firewalld/services/xray.xml <<EOF | |
<?xml version="1.0" encoding="utf-8"?> | |
<service> | |
<short>Xray</short> | |
<description>Xray port</description> | |
<port protocol="tcp" port="${XRAY_PORT}"/> | |
<port protocol="udp" port="${XRAY_PORT}"/> | |
</service> | |
EOF | |
# Configure the firewall to open the xray port | |
firewall-cmd --reload | |
firewall-cmd --add-service=xray --permanent | |
firewall-cmd --reload | |
} | |
# Execute the main function | |
main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment