Multi-location Nginx proxy support

This commit is contained in:
Samuel Huang
2021-09-13 16:35:17 +10:00
parent fbeb4be83d
commit be78e9ec32
14 changed files with 731 additions and 73 deletions

View File

@@ -18,16 +18,23 @@ RUN apk update && apk add bash nginx openssl curl socat jq moreutils
RUN cd /root; curl -sSL "https://github.com/acmesh-official/acme.sh/archive/refs/tags/2.9.0.tar.gz"|tar zxvf - RUN cd /root; curl -sSL "https://github.com/acmesh-official/acme.sh/archive/refs/tags/2.9.0.tar.gz"|tar zxvf -
RUN cd /root; mv acme.sh-2.9.0 .acme.sh RUN cd /root; mv acme.sh-2.9.0 .acme.sh
COPY site-ssl-grpc.conf.tpl /etc/nginx/http.d/ COPY site-ssl.conf.tpl /etc/nginx/http.d/
COPY grpc.tpl /etc/nginx/http.d/
COPY ws.tpl /etc/nginx/http.d/
ADD run.sh /run.sh ADD run.sh /run.sh
ADD server-ltx.sh /server-ltx.sh ADD server-ltx.sh /server-ltx.sh
ADD server-ltt.sh /server-ltt.sh ADD server-ltt.sh /server-ltt.sh
ADD server-lttw.sh /server-lttw.sh ADD server-lttw.sh /server-lttw.sh
ADD server-ltpw.sh /server-ltpw.sh
ADD server-mtt.sh /server-mtt.sh ADD server-mtt.sh /server-mtt.sh
ADD server-mttw.sh /server-mttw.sh ADD server-mttw.sh /server-mttw.sh
ADD server-mtpw.sh /server-mtpw.sh
ADD server-ttt.sh /server-ttt.sh ADD server-ttt.sh /server-ttt.sh
ADD server-tttw.sh /server-tttw.sh ADD server-tttw.sh /server-tttw.sh
ADD server-ttpw.sh /server-ttpw.sh
ADD server-lttg.sh /server-lttg.sh ADD server-lttg.sh /server-lttg.sh
ADD server-ltpg.sh /server-ltpg.sh
ADD server-nginx.sh /server-nginx.sh
RUN chmod 755 /*.sh RUN chmod 755 /*.sh

View File

@@ -18,16 +18,23 @@ RUN apk update && apk add bash nginx openssl curl socat jq moreutils
RUN cd /root; curl -sSL "https://github.com/acmesh-official/acme.sh/archive/refs/tags/2.9.0.tar.gz"|tar zxvf - RUN cd /root; curl -sSL "https://github.com/acmesh-official/acme.sh/archive/refs/tags/2.9.0.tar.gz"|tar zxvf -
RUN cd /root; mv acme.sh-2.9.0 .acme.sh RUN cd /root; mv acme.sh-2.9.0 .acme.sh
COPY site-ssl-grpc.conf.tpl /etc/nginx/http.d/ COPY site-ssl.conf.tpl /etc/nginx/http.d/
COPY grpc.tpl /etc/nginx/http.d/
COPY ws.tpl /etc/nginx/http.d/
ADD run.sh /run.sh ADD run.sh /run.sh
ADD server-ltx.sh /server-ltx.sh ADD server-ltx.sh /server-ltx.sh
ADD server-ltt.sh /server-ltt.sh ADD server-ltt.sh /server-ltt.sh
ADD server-lttw.sh /server-lttw.sh ADD server-lttw.sh /server-lttw.sh
ADD server-ltpw.sh /server-ltpw.sh
ADD server-mtt.sh /server-mtt.sh ADD server-mtt.sh /server-mtt.sh
ADD server-mttw.sh /server-mttw.sh ADD server-mttw.sh /server-mttw.sh
ADD server-mtpw.sh /server-mtpw.sh
ADD server-ttt.sh /server-ttt.sh ADD server-ttt.sh /server-ttt.sh
ADD server-tttw.sh /server-tttw.sh ADD server-tttw.sh /server-tttw.sh
ADD server-ttpw.sh /server-ttpw.sh
ADD server-lttg.sh /server-lttg.sh ADD server-lttg.sh /server-lttg.sh
ADD server-ltpg.sh /server-ltpg.sh
ADD server-nginx.sh /server-nginx.sh
RUN chmod 755 /*.sh RUN chmod 755 /*.sh

View File

@@ -18,16 +18,23 @@ RUN apk update && apk add bash nginx openssl curl socat jq moreutils
RUN cd /root; curl -sSL "https://github.com/acmesh-official/acme.sh/archive/refs/tags/2.9.0.tar.gz"|tar zxvf - RUN cd /root; curl -sSL "https://github.com/acmesh-official/acme.sh/archive/refs/tags/2.9.0.tar.gz"|tar zxvf -
RUN cd /root; mv acme.sh-2.9.0 .acme.sh RUN cd /root; mv acme.sh-2.9.0 .acme.sh
COPY site-ssl-grpc.conf.tpl /etc/nginx/http.d/ COPY site-ssl.conf.tpl /etc/nginx/http.d/
COPY grpc.tpl /etc/nginx/http.d/
COPY ws.tpl /etc/nginx/http.d/
ADD run.sh /run.sh ADD run.sh /run.sh
ADD server-ltx.sh /server-ltx.sh ADD server-ltx.sh /server-ltx.sh
ADD server-ltt.sh /server-ltt.sh ADD server-ltt.sh /server-ltt.sh
ADD server-lttw.sh /server-lttw.sh ADD server-lttw.sh /server-lttw.sh
ADD server-ltpw.sh /server-ltpw.sh
ADD server-mtt.sh /server-mtt.sh ADD server-mtt.sh /server-mtt.sh
ADD server-mttw.sh /server-mttw.sh ADD server-mttw.sh /server-mttw.sh
ADD server-mtpw.sh /server-mtpw.sh
ADD server-ttt.sh /server-ttt.sh ADD server-ttt.sh /server-ttt.sh
ADD server-tttw.sh /server-tttw.sh ADD server-tttw.sh /server-tttw.sh
ADD server-ttpw.sh /server-ttpw.sh
ADD server-lttg.sh /server-lttg.sh ADD server-lttg.sh /server-lttg.sh
ADD server-ltpg.sh /server-ltpg.sh
ADD server-nginx.sh /server-nginx.sh
RUN chmod 755 /*.sh RUN chmod 755 /*.sh

9
grpc.tpl Normal file
View File

@@ -0,0 +1,9 @@
location LOCATION {
if ($content_type !~ "application/grpc") {
return 404;
}
client_max_body_size 0;
client_body_timeout 1071906480m;
grpc_read_timeout 1071906480m;
grpc_pass grpc://127.0.0.1:PORT;
}

62
run.sh
View File

@@ -6,24 +6,30 @@ XCONF=/tmp/server-xray.json
usage() { usage() {
echo "server-xray <server-options>" echo "server-xray <server-options>"
echo " --ltx <VLESS-TCP-XTLS option> [p=443,]d=domain.com,u=id[:level[:email]][,f=[fb-host]:fb-port:[fb-path]]" echo " --ltx <VLESS-TCP-XTLS option> [p=443,]d=domain.com,u=id[:level[:email]][,f=[fb-host]:fb-port:[fb-path]]"
echo " --ltt <VLESS-TCP-TLS option> [p=443,]d=domain.com,u=id[:level[:email]][,f=[fb-host]:fb-port:[fb-path]]" echo " --ltt <VLESS-TCP-TLS option> [p=443,]d=domain.com,u=id[:level[:email]][,f=[fb-host]:fb-port:[fb-path]]"
echo " --lttw <VLESS-TCP-TLS-WS option> [p=443,]d=domain.com,u=id[:level[:email]][,f=[fb-host]:fb-port:[fb-path]],w=/webpath" echo " --lttw <VLESS-TCP-TLS-WS option> [p=443,]d=domain.com,u=id[:level[:email]][,f=[fb-host]:fb-port:[fb-path]],w=/webpath"
echo " --lttg <VLESS-TCP-TLS-GRPC option> [p=443,]d=domain.com,u=id[:level[:email]],s=/svcpath,g=grpcport" echo " --ltpw <VLESS-TCP-PLAIN-WS option> [p=443,]u=id[:level[:email]][,f=[fb-host]:fb-port:[fb-path]],w=/webpath"
echo " --mtt <VMESS-TCP-TLS option> [p=443,]d=domain.com,u=id[:level[:email]][,f=[fb-host]:fb-port:[fb-path]]" echo " --lttg <VLESS-TCP-TLS-GRPC option> [p=443,]d=domain.com,u=id[:level[:email]],s=/svcpath"
echo " --mttw <VMESS-TCP-TLS-WS option> [p=443,]d=domain.com,u=id[:level[:email]][,f=[fb-host]:fb-port:[fb-path]],w=/webpath" echo " --ltpg <VLESS-TCP-PLAIN-GRPC option> [p=443,]u=id[:level[:email]],s=/svcpath"
echo " --ttt <TROJAN-TCP-TLS option> [p=443,]d=domain.com,u=psw[:level[:email]][,f=[fb-host]:fb-port:[fb-path]]" echo " --mtt <VMESS-TCP-TLS option> [p=443,]d=domain.com,u=id[:level[:email]][,f=[fb-host]:fb-port:[fb-path]]"
echo " --tttw <TROJAN-TCP-TLS-WS option> [p=443,]d=domain.com,u=psw[:level[:email]][,f=[fb-host]:fb-port:[fb-path]],w=/webpath" echo " --mttw <VMESS-TCP-TLS-WS option> [p=443,]d=domain.com,u=id[:level[:email]][,f=[fb-host]:fb-port:[fb-path]],w=/webpath"
# echo " --ssa <Shadowsocks-AEAD option> [port=443,]user=password1:method1[,user=password2:method2]" echo " --mtpw <VMESS-TCP-PLAIN-WS option> [p=443,]u=id[:level[:email]][,f=[fb-host]:fb-port:[fb-path]],w=/webpath"
# echo " --sst <Shadowsocks-TCP option> [port=443,]user=passwd,method=xxxx" echo " --ttt <TROJAN-TCP-TLS option> [p=443,]d=domain.com,u=psw[:level[:email]][,f=[fb-host]:fb-port:[fb-path]]"
echo " -k|--hook <hook-url> [Optional] DDNS update or notifing URL to be hit" echo " --tttw <TROJAN-TCP-TLS-WS option> [p=443,]d=domain.com,u=psw[:level[:email]][,f=[fb-host]:fb-port:[fb-path]],w=/webpath"
echo " -r|--request-domain <domain-name> [Optional] Domain name to request for letsencrypt cert" echo " --ttpw <TROJAN-TCP-PLAIN-WS option> [p=443,]u=psw[:level[:email]][,f=[fb-host]:fb-port:[fb-path]],w=/webpath"
echo " -c|--cert-path <cert-path-root> [Optional] Reading TLS certs from folder <cert-path-root>/<domain-name>/" # echo " --ssa <Shadowsocks-AEAD option> [port=443,]user=password1:method1[,user=password2:method2]"
echo " -i|--stdin [Optional] Read config from stdin instead of auto generation" # echo " --sst <Shadowsocks-TCP option> [port=443,]user=passwd,method=xxxx"
echo " -d|--debug [Optional] Start in debug mode with verbose output" echo " --ng-opt <nginx-options> [p=443,]d=domain.com"
echo " --ng-proxy <nginx-proxy-options> [h=127.0.0.1,]p=8443,l=location,n=ws|grpc"
echo " -k|--hook <hook-url> [Optional] DDNS update or notifing URL to be hit"
echo " -r|--request-domain <domain-name> [Optional] Domain name to request for letsencrypt cert"
echo " -c|--cert-path <cert-path-root> [Optional] Reading TLS certs from folder <cert-path-root>/<domain-name>/"
echo " -i|--stdin [Optional] Read config from stdin instead of auto generation"
echo " -d|--debug [Optional] Start in debug mode with verbose output"
} }
TEMP=`getopt -o k:r:c:di --long hook:,request-domain:,cert-path:,ltx:,ltt:,lttw:,mtt:,mttw:,ttt:,tttw:,lttg:,ssa:,sst:stdin,debug -n "$0" -- $@` TEMP=`getopt -o k:r:c:di --long hook:,request-domain:,cert-path:,ltx:,ltt:,lttw:,ltpw:,mtt:,mttw:,mtpw:,ttt:,tttw:,ttpw:,lttg:,ltpg:,ssa:,sst:,ng-opt:,ng-proxy:,stdin,debug -n "$0" -- $@`
if [ $? != 0 ] ; then usage; exit 1 ; fi if [ $? != 0 ] ; then usage; exit 1 ; fi
eval set -- "$TEMP" eval set -- "$TEMP"
@@ -49,11 +55,19 @@ while true ; do
DEBUG=1 DEBUG=1
shift 1 shift 1
;; ;;
--ltx|--ltt|--lttw|--lttg|--mtt|--mttw|--ttt|--tttw) --ltx|--ltt|--lttw|--ltpw|--lttg|--ltpg|--mtt|--mttw|--mtpw|--ttt|--tttw|--ttpw)
if [ "$1" = "--lttg" ]; then NGINX=1; fi if [ "$1" = "--lttg" ]; then NGINX=1; fi
SVC=`echo $1|tr -d '\-\-'` SVC=`echo $1|tr -d '\-\-'`
SVCMD+=("${DIR}server-${SVC}.sh $2") SVCMD+=("${DIR}server-${SVC}.sh $2")
shift 2 shift 2
;;
--ng-opt)
NGOPT=$2
shift 2
;;
--ng-proxy)
NGPROXY+=("$2")
shift 2
;; ;;
--) --)
shift shift
@@ -117,14 +131,26 @@ if [ -n "${SVCMD}" ]; then
exit 1 exit 1
fi fi
done done
if [ "${DEBUG}" = "1" ]; then if [ "${DEBUG}" = "1" ]; then
cat $XCONF |jq '.log.loglevel |="debug"' |sponge $XCONF cat $XCONF |jq '.log.loglevel |="debug"' |sponge $XCONF
echo echo
cat $XCONF cat $XCONF
echo echo
fi fi
if [ "${NGINX}" = "1" ]; then nginx; fi
if [ -n "${NGOPT}" ]; then
ngcmd="${DIR}server-nginx.sh --ng-opt ${NGOPT},$xopt"
for ngproxy in "${NGPROXY[@]}"
do
ngcmd="${ngcmd} --ng-proxy ${ngproxy}"
done
$ngcmd
nginx;
fi
exec /usr/local/bin/xray -c $XCONF exec /usr/local/bin/xray -c $XCONF
else else
if [ "${STDINCONF}" = "1" ]; then if [ "${STDINCONF}" = "1" ]; then
exec /usr/local/bin/xray exec /usr/local/bin/xray

80
server-ltpg.sh Executable file
View File

@@ -0,0 +1,80 @@
#!/bin/bash
usage() {
echo "Usage: server-lttg <xconf=xray-config-file>,<port=443>,<user=xxx-xxx[:0[:a@mail.com]]>,<service=svcname>"
}
options=(`echo $1 |tr ',' ' '`)
for option in "${options[@]}"
do
kv=(`echo $option |tr '=' ' '`)
case "${kv[0]}" in
x|xconf)
xconf="${kv[1]}"
;;
p|port)
port="${kv[1]}"
;;
u|user)
xuser+=("${kv[1]}")
;;
s|service)
service="${kv[1]}"
;;
esac
done
if [ -z "${xconf}" ]; then
echo "Error: xconf undefined."
usage
exit 1
fi
if [ -z "${port}" ]; then
port=443
fi
if [ -z "${xuser}" ]; then
echo "Error: user undefined."
usage
exit 1
fi
if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi
XCONF=$xconf
cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"vless", "settings":{"clients":[]}}]' |sponge $XCONF
for xu in "${xuser[@]}"
do
IFS=':'
uopt=(${xu})
uopt=(${uopt[@]})
if [ -z "${uopt[0]}" ]; then
echo "Incorrect user format: ${xu}"
echo "Correct user format: user=<uid>[:level:email]"
echo "Like: user=myid:0:nobody@g.cn"
echo "Like: user=myid::nobody@g.cn"
echo "Like: user=myid:0"
echo "Like: user=myid"
exit 1
fi
if [ -z "${uopt[1]}" ]; then
uopt[1]=0
fi
if [ -z "${uopt[2]}" ]; then
uopt[2]="nobody@g.cn"
fi
cat $XCONF |jq --arg port "${port}" --arg uid "${uopt[0]}" --arg level "${uopt[1]}" --arg email "${uopt[2]}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .settings.clients ) += [ {"id":$uid, "level":($level|tonumber), "email":$email} ] ' \
|sponge $XCONF
done
cat $XCONF |jq --arg port "${port}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' \
|sponge $XCONF
cat $XCONF |jq --arg port "${port}" --arg service "${service}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"grpc", "grpcSettings":{"serviceName":$service}, "security":"none"} ' \
|sponge $XCONF

132
server-ltpw.sh Executable file
View File

@@ -0,0 +1,132 @@
#!/bin/bash
usage() {
echo "Usage: server-ltpw <xconf=xray-config-file>,<port=443>,<user=myid[:0[:a@mail.com]]>,<path=websocket-path>[,fallback=www.baidu.com:443:/html][,fallback=:2443:/websocket2]"
}
options=(`echo $1 |tr ',' ' '`)
for option in "${options[@]}"
do
kv=(`echo $option |tr '=' ' '`)
case "${kv[0]}" in
x|xconf)
xconf="${kv[1]}"
;;
p|port)
port="${kv[1]}"
;;
u|user)
xuser+=("${kv[1]}")
;;
w|wpath)
wspath="${kv[1]}"
;;
f|fallback)
fallback+=("${kv[1]}")
;;
esac
done
if [ -z "${xconf}" ]; then
echo "Error: xconf undefined."
usage
exit 1
fi
if [ -z "${port}" ]; then
port=443
fi
if [ -z "${xuser}" ]; then
echo "Error: user undefined."
usage
exit 1
fi
if [ -z "${wspath}" ]; then
echo "Error: wspath undefined."
usage
exit 1
fi
if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi
XCONF=$xconf
cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"vless", "settings":{"clients":[]}}]' |sponge $XCONF
for xu in "${xuser[@]}"
do
IFS=':'
uopt=(${xu})
uopt=(${uopt[@]})
if [ -z "${uopt[0]}" ]; then
echo "Incorrect user format: ${xu}"
echo "Correct user format: user=<uid>[:level:email]"
echo "Like: user=myid:0:nobody@g.cn"
echo "Like: user=myid::nobody@g.cn"
echo "Like: user=myid:0"
echo "Like: user=myid"
exit 1
fi
if [ -z "${uopt[1]}" ]; then
uopt[1]=0
fi
if [ -z "${uopt[2]}" ]; then
uopt[2]="nobody@g.cn"
fi
cat $XCONF |jq --arg port "${port}" --arg uid "${uopt[0]}" --arg level "${uopt[1]}" --arg email "${uopt[2]}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .settings.clients ) += [ {"id":$uid, "level":($level|tonumber), "email":$email} ] ' \
|sponge $XCONF
done
cat $XCONF |jq --arg port "${port}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' \
|sponge $XCONF
for fb in "${fallback[@]}"
do
IFS=':'
fopt=(${fb})
fopt=(${fopt[@]})
fhost="${fopt[0]}"
fport="${fopt[1]}"
fpath="${fopt[2]}"
if [ -z "${fport}" ]; then
echo "Incorrect fallback format: ${fb}"
echo "Correct fallback: fallback=[host]<:port>[:path]"
echo "Like: fallback=baidu.com:443:/websocket"
echo "Like: fallback=:1443:/websocket"
echo "Like: fallback=:1443"
exit 1
fi
if [ -z "${fhost}" ]; then
if [ -z "${fpath}" ]; then
Jfallback=`echo '{}' |jq --arg fport "${fport}" --arg fpath "${fpath}" '. += {"dest":($fport|tonumber), "xver":1}'`
else
Jfallback=`echo '{}' |jq --arg fport "${fport}" --arg fpath "${fpath}" '. += {"dest":($fport|tonumber), "path":$fpath, "xver":1}'`
fi
else
if [ -z "${fpath}" ]; then
fdest="${fhost}:${fport}"
Jfallback=`echo '{}' |jq --arg fdest "${fdest}" --arg fpath "${fpath}" '. += {"dest":$fdest, "xver":1}'`
else
Jfallback=`echo '{}' |jq --arg fdest "${fdest}" --arg fpath "${fpath}" '. += {"dest":$fdest, "path":$fpath, "xver":1}'`
fi
fi
cat $XCONF |jq --arg port "${port}" --argjson jfallback "$Jfallback" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .settings.fallbacks ) += [ $jfallback ] ' \
|sponge $XCONF
done
cat $XCONF |jq --arg port "${port}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"ws", "security":"none" } ' \
|sponge $XCONF
cat $XCONF |jq --arg port "${port}" --arg wspath "${wspath}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"wsSettings":{"path":$wspath}} ' \
|sponge $XCONF

View File

@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
usage() { usage() {
echo "Usage: server-lttg <xconf=xray-config-file>,<certpath=cert-path-root>,<port=443>,<domain=mydomain.com>,<user=xxx-xxx[:0[:a@mail.com]]>,<service=svcname>,<gport=65443>" echo "Usage: server-lttg <xconf=xray-config-file>,<certpath=cert-path-root>,<port=443>,<domain=mydomain.com>,<user=xxx-xxx[:0[:a@mail.com]]>,<service=svcname>"
} }
options=(`echo $1 |tr ',' ' '`) options=(`echo $1 |tr ',' ' '`)
@@ -24,9 +24,6 @@ do
u|user) u|user)
xuser+=("${kv[1]}") xuser+=("${kv[1]}")
;; ;;
g|gport)
gport="${kv[1]}"
;;
s|service) s|service)
service="${kv[1]}" service="${kv[1]}"
;; ;;
@@ -49,12 +46,6 @@ if [ -z "${port}" ]; then
port=443 port=443
fi fi
if [ -z "${gport}" ]; then
echo "Error: gport undefined."
usage
exit 1
fi
if [ -z "${domain}" ]; then if [ -z "${domain}" ]; then
echo "Error: domain undefined." echo "Error: domain undefined."
usage usage
@@ -68,10 +59,9 @@ if [ -z "${xuser}" ]; then
fi fi
if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi
if ! [ "${gport}" -eq "${gport}" ] 2>/dev/null; then >&2 echo "Gport number must be numeric"; exit 1; fi
XCONF=$xconf XCONF=$xconf
cat $XCONF |jq --arg gport "${gport}" '.inbounds +=[{"port":($gport|tonumber), "protocol":"vless", "settings":{"clients":[]}}]' |sponge $XCONF cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"vless", "settings":{"clients":[]}}]' |sponge $XCONF
for xu in "${xuser[@]}" for xu in "${xuser[@]}"
do do
@@ -94,17 +84,21 @@ do
if [ -z "${uopt[2]}" ]; then if [ -z "${uopt[2]}" ]; then
uopt[2]="nobody@g.cn" uopt[2]="nobody@g.cn"
fi fi
cat $XCONF |jq --arg gport "${gport}" --arg uid "${uopt[0]}" --arg level "${uopt[1]}" --arg email "${uopt[2]}" \ cat $XCONF |jq --arg port "${port}" --arg uid "${uopt[0]}" --arg level "${uopt[1]}" --arg email "${uopt[2]}" \
'( .inbounds[] | select(.port == ($gport|tonumber)) | .settings.clients ) += [ {"id":$uid, "level":($level|tonumber), "email":$email} ] ' \ '( .inbounds[] | select(.port == ($port|tonumber)) | .settings.clients ) += [ {"id":$uid, "level":($level|tonumber), "email":$email} ] ' \
|sponge $XCONF |sponge $XCONF
done done
cat $XCONF |jq --arg gport "${gport}" \ cat $XCONF |jq --arg port "${port}" \
'( .inbounds[] | select(.port == ($gport|tonumber)) | .settings.decryption ) += "none" ' \ '( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' \
|sponge $XCONF |sponge $XCONF
cat $XCONF |jq --arg gport "${gport}" --arg service "${service}" \ cat $XCONF |jq --arg port "${port}" --arg service "${service}" \
'( .inbounds[] | select(.port == ($gport|tonumber)) | .streamSettings ) += {"network":"grpc", "grpcSettings":{"serviceName":$service} } ' \ '( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"grpc", "grpcSettings":{"serviceName":$service}, "security":"tls"} ' \
|sponge $XCONF
cat $XCONF |jq --arg port "${port}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{"alpn":["http/2"]}} ' \
|sponge $XCONF |sponge $XCONF
for certroot in "${certpath[@]}" for certroot in "${certpath[@]}"
@@ -122,26 +116,6 @@ if [ ! -f "${fullchain}" ] || [ ! -f "${prvkey}" ]; then
exit 2 exit 2
fi fi
# Running as root to enable low port listening. Necessary for Fargate or k8s. cat $XCONF |jq --arg port "${port}" --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \
sed -i 's/^user nginx;$/user root;/g' /etc/nginx/nginx.conf '( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings.tlsSettings ) += {"certificates":[{"certificateFile":$fullchain, "keyFile":$prvkey}]} ' \
mkdir -p /run/nginx/ |sponge $XCONF
cd /etc/nginx/http.d/
if [ -f /etc/nginx/http.d/default.conf ]; then
mv default.conf default.conf.disable
fi
TPL="site-ssl-grpc.conf.tpl"
ESC_CERTFILE=$(printf '%s\n' "${fullchain}" | sed -e 's/[]\/$*.^[]/\\&/g')
ESC_PRVKEYFILE=$(printf '%s\n' "${prvkey}" | sed -e 's/[]\/$*.^[]/\\&/g')
ESC_GSVC=$(printf '%s\n' "${service}" | sed -e 's/[]\/$*.^[]/\\&/g')
cat ${TPL} \
| sed "s/CERTFILE/${ESC_CERTFILE}/g" \
| sed "s/PRVKEYFILE/${ESC_PRVKEYFILE}/g" \
| sed "s/NGDOMAIN/${domain}/g" \
| sed "s/NGPORT/${port}/g" \
| sed "s/GPORT/${gport}/g" \
| sed "s/GSVC/${ESC_GSVC}/g" \
>site-xray.conf

View File

@@ -142,11 +142,11 @@ do
done done
cat $XCONF |jq --arg port "${port}" \ cat $XCONF |jq --arg port "${port}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"ws", "security":"tls" } ' \ '( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"ws", "security":"tls"} ' \
|sponge $XCONF |sponge $XCONF
cat $XCONF |jq --arg port "${port}" \ cat $XCONF |jq --arg port "${port}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{"alpn":["http/1.1"]} } ' \ '( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{"alpn":["http/1.1"]}} ' \
|sponge $XCONF |sponge $XCONF
cat $XCONF |jq --arg port "${port}" --arg wspath "${wspath}" \ cat $XCONF |jq --arg port "${port}" --arg wspath "${wspath}" \

132
server-mtpw.sh Executable file
View File

@@ -0,0 +1,132 @@
#!/bin/bash
usage() {
echo "Usage: server-mtpw <xconf=xray-config-file>,<port=443>,<user=myid[:0[:a@mail.com]]>,<path=websocket-path>[,fallback=www.baidu.com:443:/html][,fallback=:2443:/websocket2]"
}
options=(`echo $1 |tr ',' ' '`)
for option in "${options[@]}"
do
kv=(`echo $option |tr '=' ' '`)
case "${kv[0]}" in
x|xconf)
xconf="${kv[1]}"
;;
p|port)
port="${kv[1]}"
;;
u|user)
xuser+=("${kv[1]}")
;;
w|wpath)
wspath="${kv[1]}"
;;
f|fallback)
fallback+=("${kv[1]}")
;;
esac
done
if [ -z "${xconf}" ]; then
echo "Error: xconf undefined."
usage
exit 1
fi
if [ -z "${port}" ]; then
port=443
fi
if [ -z "${xuser}" ]; then
echo "Error: user undefined."
usage
exit 1
fi
if [ -z "${wspath}" ]; then
echo "Error: wspath undefined."
usage
exit 1
fi
if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi
XCONF=$xconf
cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"vmess", "settings":{"clients":[]}}]' |sponge $XCONF
for xu in "${xuser[@]}"
do
IFS=':'
uopt=(${xu})
uopt=(${uopt[@]})
if [ -z "${uopt[0]}" ]; then
echo "Incorrect user format: ${xu}"
echo "Correct user format: user=<uid>[:level:email]"
echo "Like: user=myid:0:nobody@g.cn"
echo "Like: user=myid::nobody@g.cn"
echo "Like: user=myid:0"
echo "Like: user=myid"
exit 1
fi
if [ -z "${uopt[1]}" ]; then
uopt[1]=0
fi
if [ -z "${uopt[2]}" ]; then
uopt[2]="nobody@g.cn"
fi
cat $XCONF |jq --arg port "${port}" --arg uid "${uopt[0]}" --arg level "${uopt[1]}" --arg email "${uopt[2]}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .settings.clients ) += [ {"id":$uid, "level":($level|tonumber), "email":$email} ] ' \
|sponge $XCONF
done
cat $XCONF |jq --arg port "${port}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' \
|sponge $XCONF
for fb in "${fallback[@]}"
do
IFS=':'
fopt=(${fb})
fopt=(${fopt[@]})
fhost="${fopt[0]}"
fport="${fopt[1]}"
fpath="${fopt[2]}"
if [ -z "${fport}" ]; then
echo "Incorrect fallback format: ${fb}"
echo "Correct fallback: fallback=[host]<:port>[:path]"
echo "Like: fallback=baidu.com:443:/websocket"
echo "Like: fallback=:1443:/websocket"
echo "Like: fallback=:1443"
exit 1
fi
if [ -z "${fhost}" ]; then
if [ -z "${fpath}" ]; then
Jfallback=`echo '{}' |jq --arg fport "${fport}" --arg fpath "${fpath}" '. += {"dest":($fport|tonumber), "xver":1}'`
else
Jfallback=`echo '{}' |jq --arg fport "${fport}" --arg fpath "${fpath}" '. += {"dest":($fport|tonumber), "path":$fpath, "xver":1}'`
fi
else
if [ -z "${fpath}" ]; then
fdest="${fhost}:${fport}"
Jfallback=`echo '{}' |jq --arg fdest "${fdest}" --arg fpath "${fpath}" '. += {"dest":$fdest, "xver":1}'`
else
Jfallback=`echo '{}' |jq --arg fdest "${fdest}" --arg fpath "${fpath}" '. += {"dest":$fdest, "path":$fpath, "xver":1}'`
fi
fi
cat $XCONF |jq --arg port "${port}" --argjson jfallback "$Jfallback" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .settings.fallbacks ) += [ $jfallback ] ' \
|sponge $XCONF
done
cat $XCONF |jq --arg port "${port}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"ws", "security":"none" } ' \
|sponge $XCONF
cat $XCONF |jq --arg port "${port}" --arg wspath "${wspath}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"wsSettings":{"path":$wspath}} ' \
|sponge $XCONF

143
server-nginx.sh Executable file
View File

@@ -0,0 +1,143 @@
#!/bin/bash
DIR=`dirname $0`
DIR="$(cd $DIR; pwd)"
usage() {
echo "Usage: server-nginx --ng-opt <nginx-options> --ng-proxy <nginx-proxy-options>"
}
TEMP=`getopt -o o:x: --long ng-opt:,ng-proxy: -n "$0" -- $@`
if [ $? != 0 ] ; then usage; exit 1 ; fi
eval set -- "$TEMP"
while true ; do
case "$1" in
-o|--ng-opt)
NGOPT="$2"
shift 2
;;
-x|--ng-proxy)
NGPROXY+=("$2")
shift 2
;;
--)
shift
break
;;
*)
echo "Unrecogonised opt: $1"
usage;
exit 1
;;
esac
done
options=(`echo $NGOPT |tr ',' ' '`)
for option in "${options[@]}"
do
kv=(`echo $option |tr '=' ' '`)
case "${kv[0]}" in
c|certpath)
certpath+=("${kv[1]}")
;;
p|port)
port="${kv[1]}"
;;
d|domain)
domain="${kv[1]}"
;;
esac
done
if [ -z "${certpath}" ]; then
echo "Error: certpath undefined."
usage
exit 1
fi
if [ -z "${port}" ]; then
port=443
fi
if [ -z "${domain}" ]; then
echo "Error: domain undefined."
usage
exit 1
fi
if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi
for certroot in "${certpath[@]}"
do
if [ -f "${certroot}/${domain}/fullchain.cer" ] && [ -f "${certroot}/${domain}/${domain}.key" ]; then
fullchain="${certroot}/${domain}/fullchain.cer"
prvkey="${certroot}/${domain}/${domain}.key"
break
fi
done
if [ ! -f "${fullchain}" ] || [ ! -f "${prvkey}" ]; then
echo "TLS cert missing?"
echo "Abort."
exit 2
fi
# Running as root to enable low port listening. Necessary for Fargate or k8s.
sed -i 's/^user nginx;$/user root;/g' /etc/nginx/nginx.conf
mkdir -p /run/nginx/
cd /etc/nginx/http.d/
if [ -f /etc/nginx/http.d/default.conf ]; then
mv default.conf default.conf.disable
fi
TPL="site-ssl.conf.tpl"
ESC_CERTFILE=$(printf '%s\n' "${fullchain}" | sed -e 's/[]\/$*.^[]/\\&/g')
ESC_PRVKEYFILE=$(printf '%s\n' "${prvkey}" | sed -e 's/[]\/$*.^[]/\\&/g')
cat ${TPL} \
| sed "s/CERTFILE/${ESC_CERTFILE}/g" \
| sed "s/PRVKEYFILE/${ESC_PRVKEYFILE}/g" \
| sed "s/NGDOMAIN/${domain}/g" \
| sed "s/NGPORT/${port}/g" \
>site-xray.conf
for ngproxy in "${NGPROXY[@]}"
do
options=(`echo $ngproxy |tr ',' ' '`)
for option in "${options[@]}"
do
kv=(`echo $option |tr '=' ' '`)
case "${kv[0]}" in
h|host)
xhost="${kv[1]}"
;;
p|port)
xport="${kv[1]}"
;;
l|location)
xlocation="${kv[1]}"
;;
n|network)
xnetwork="${kv[1]}"
;;
esac
done
# Replace the last(only) single line '}' with specific tpl file, hence insert a new section into the Nginx config file
case "${xnetwork}" in
ws|websocket)
sed -i -e "/^\}$/r ws.tpl" -e "/^\}$/d" site-xray.conf
;;
grpc)
sed -i -e "/^\}$/r grpc.tpl" -e "/^\}$/d" site-xray.conf
;;
esac
# Then add '}' to the end of the Nginx config file
echo -e "\n}" >> site-xray.conf
ESC_LOCATION=$(printf '%s\n' "${xlocation}" | sed -e 's/[]\/$*.^[]/\\&/g')
sed -i "s/PORT/${xport}/g" site-xray.conf
sed -i "s/LOCATION/${ESC_LOCATION}/g" site-xray.conf
done

136
server-ttpw.sh Executable file
View File

@@ -0,0 +1,136 @@
#!/bin/bash
usage() {
echo "Usage: server-ttpw <xconf=xray-config-file>,<port=443>,<user=password[:level[:email]],<path=websocket-path>[,fallback=www.baidu.com:443:/html][,fallback=:2443:/websocket2]"
}
options=(`echo $1 |tr ',' ' '`)
for option in "${options[@]}"
do
kv=(`echo $option |tr '=' ' '`)
case "${kv[0]}" in
x|xconf)
xconf="${kv[1]}"
;;
p|port)
port="${kv[1]}"
;;
u|user)
xuser+=("${kv[1]}")
;;
w|wpath)
wspath="${kv[1]}"
;;
f|fallback)
fallback+=("${kv[1]}")
;;
esac
done
if [ -z "${xconf}" ]; then
echo "Error: xconf undefined."
usage
exit 1
fi
if [ -z "${port}" ]; then
port=443
fi
if [ -z "${xuser}" ]; then
echo "Error: user undefined."
usage
exit 1
fi
if [ -z "${wspath}" ]; then
echo "Error: wspath undefined."
usage
exit 1
fi
if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi
XCONF=$xconf
cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"trojan", "settings":{"clients":[]}}]' |sponge $XCONF
for xu in "${xuser[@]}"
do
IFS=':'
uopt=(${xu})
uopt=(${uopt[@]})
if [ -z "${uopt[0]}" ]; then
echo "Incorrect user format: ${xu}"
echo "Correct user format: user=password[:level[:email]"
echo "Like: user=mypass:0:me@g.cn"
echo "Like: user=mypass::me@g.cn"
echo "Like: user=mypass:0"
echo "Like: user=mypass"
exit 1
fi
if [ -z "${uopt[1]}" ]; then
uopt[1]=0
fi
if [ -z "${uopt[2]}" ]; then
uopt[2]="nobody@g.cn"
fi
cat $XCONF |jq --arg port "${port}" --arg pass "${uopt[0]}" --arg level "${uopt[1]}" --arg email "${uopt[2]}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .settings.clients ) += [ {"password":$pass, "level":($level|tonumber), "email":$email} ] ' \
|sponge $XCONF
done
cat $XCONF |jq --arg port "${port}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' \
|sponge $XCONF
for fb in "${fallback[@]}"
do
IFS=':'
fopt=(${fb})
fopt=(${fopt[@]})
fhost="${fopt[0]}"
fport="${fopt[1]}"
fpath="${fopt[2]}"
if [ -z "${fport}" ]; then
echo "Incorrect fallback format: ${fb}"
echo "Correct fallback: fallback=[host]<:port>[:path]"
echo "Like: fallback=baidu.com:443:/websocket"
echo "Like: fallback=:1443:/websocket"
echo "Like: fallback=:1443"
exit 1
fi
if [ -z "${fhost}" ]; then
if [ -z "${fpath}" ]; then
Jfallback=`echo '{}' |jq --arg fport "${fport}" --arg fpath "${fpath}" '. += {"dest":($fport|tonumber), "xver":1}'`
else
Jfallback=`echo '{}' |jq --arg fport "${fport}" --arg fpath "${fpath}" '. += {"dest":($fport|tonumber), "path":$fpath, "xver":1}'`
fi
else
if [ -z "${fpath}" ]; then
fdest="${fhost}:${fport}"
Jfallback=`echo '{}' |jq --arg fdest "${fdest}" --arg fpath "${fpath}" '. += {"dest":$fdest, "xver":1}'`
else
Jfallback=`echo '{}' |jq --arg fdest "${fdest}" --arg fpath "${fpath}" '. += {"dest":$fdest, "path":$fpath, "xver":1}'`
fi
fi
cat $XCONF |jq --arg port "${port}" --argjson jfallback "$Jfallback" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .settings.fallbacks ) += [ $jfallback ] ' \
|sponge $XCONF
done
cat $XCONF |jq --arg port "${port}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"ws", "security":"none" } ' \
|sponge $XCONF
cat $XCONF |jq --arg port "${port}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{"alpn":["http/1.1"]} } ' \
|sponge $XCONF
cat $XCONF |jq --arg port "${port}" --arg wspath "${wspath}" \
'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"wsSettings":{"path":$wspath}} ' \
|sponge $XCONF

View File

@@ -13,13 +13,5 @@ server {
location / { location / {
return 404; return 404;
} }
location GSVC {
if ($content_type !~ "application/grpc") {
return 404;
}
client_max_body_size 0;
client_body_timeout 1071906480m;
grpc_read_timeout 1071906480m;
grpc_pass grpc://127.0.0.1:GPORT;
}
} }

13
ws.tpl Normal file
View File

@@ -0,0 +1,13 @@
location LOCATION {
if ($http_upgrade != "websocket") {
return 404;
}
proxy_redirect off;
proxy_pass http://127.0.0.1:PORT;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}