From a8b2ece228726807cf7e46ac2abc9b297c2f2c36 Mon Sep 17 00:00:00 2001 From: Samuel Huang Date: Tue, 10 Sep 2024 20:37:42 +1000 Subject: [PATCH] Initial REALITY support --- Dockerfile | 37 +++---- adduser.sh | 74 ++++++++++++++ addusertj.sh | 74 ++++++++++++++ fallback.sh | 79 +++++++++++++++ run.sh | 63 ++++++------ server-lpg.sh => server-lgp.sh | 77 +++++++-------- server-lgr.sh | 134 ++++++++++++++++++++++++++ server-lsg.sh => server-lgt.sh | 130 ++++++++++++++----------- server-lps.sh | 129 ------------------------- server-lpw.sh | 129 ------------------------- server-ls.sh | 155 ------------------------------ server-lsp.sh | 78 +++++++++++++++ server-lss.sh | 168 -------------------------------- server-lst.sh | 134 ++++++++++++++++++++++++++ server-ltr.sh | 125 ++++++++++++++++++++++++ server-lx.sh => server-ltsx.sh | 0 server-ltt.sh | 125 ++++++++++++++++++++++++ server-lwp.sh | 78 +++++++++++++++ server-lsw.sh => server-lwt.sh | 170 +++++++++++++-------------------- server-mpw.sh | 129 ------------------------- server-ms.sh | 155 ------------------------------ server-mtt.sh | 125 ++++++++++++++++++++++++ server-mwp.sh | 78 +++++++++++++++ server-msw.sh => server-mwt.sh | 170 +++++++++++++-------------------- server-tpw.sh | 129 ------------------------- server-ts.sh | 155 ------------------------------ server-ttt.sh | 126 ++++++++++++++++++++++++ server-twp.sh | 78 +++++++++++++++ server-tsw.sh => server-twt.sh | 170 +++++++++++++-------------------- 29 files changed, 1673 insertions(+), 1601 deletions(-) create mode 100755 adduser.sh create mode 100755 addusertj.sh create mode 100755 fallback.sh rename server-lpg.sh => server-lgp.sh (55%) create mode 100755 server-lgr.sh rename server-lsg.sh => server-lgt.sh (65%) delete mode 100755 server-lps.sh delete mode 100755 server-lpw.sh delete mode 100755 server-ls.sh create mode 100755 server-lsp.sh delete mode 100755 server-lss.sh create mode 100755 server-lst.sh create mode 100755 server-ltr.sh rename server-lx.sh => server-ltsx.sh (100%) create mode 100755 server-ltt.sh create mode 100755 server-lwp.sh rename server-lsw.sh => server-lwt.sh (50%) delete mode 100755 server-mpw.sh delete mode 100755 server-ms.sh create mode 100755 server-mtt.sh create mode 100755 server-mwp.sh rename server-msw.sh => server-mwt.sh (50%) delete mode 100755 server-tpw.sh delete mode 100755 server-ts.sh create mode 100755 server-ttt.sh create mode 100755 server-twp.sh rename server-tsw.sh => server-twt.sh (50%) diff --git a/Dockerfile b/Dockerfile index 9c1dada..79c3927 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,28 +31,33 @@ COPY nginx-proxy.tpl /etc/nginx/conf.d/ COPY nginx-grpc.tpl /etc/nginx/conf.d/ COPY nginx-ws.tpl /etc/nginx/conf.d/ -ADD server-lx.sh /server-lx.sh -ADD server-ls.sh /server-ls.sh -ADD server-ms.sh /server-ms.sh -ADD server-ts.sh /server-ts.sh +#ADD server-lgp.sh /server-lgp.sh +ADD server-lgr.sh /server-lgr.sh +ADD server-lgt.sh /server-lgt.sh -ADD server-lsw.sh /server-lsw.sh -ADD server-lsg.sh /server-lsg.sh -ADD server-lss.sh /server-lss.sh +#ADD server-lsp.sh /server-lsp.sh +ADD server-lst.sh /server-lst.sh -ADD server-msw.sh /server-msw.sh -ADD server-tsw.sh /server-tsw.sh +ADD server-ltr.sh /server-ltr.sh +ADD server-ltt.sh /server-ltt.sh -ADD server-lpw.sh /server-lpw.sh -ADD server-lpg.sh /server-lpg.sh -ADD server-lps.sh /server-lps.sh +#ADD server-lwp.sh /server-lwp.sh +ADD server-lwt.sh /server-lwt.sh -ADD server-mpw.sh /server-mpw.sh -ADD server-tpw.sh /server-tpw.sh +ADD server-mtt.sh /server-mtt.sh +#ADD server-mwp.sh /server-mwp.sh +ADD server-mwt.sh /server-mwt.sh -ADD server-nginx.sh /server-nginx.sh +#ADD server-twp.sh /server-twp.sh +ADD server-ttt.sh /server-ttt.sh +ADD server-twt.sh /server-twt.sh -ADD run.sh /run.sh +ADD server-nginx.sh /server-nginx.sh +ADD fallback.sh /fallback.sh +ADD addusertj.sh /addusertj.sh +ADD adduser.sh /adduser.sh + +ADD run.sh /run.sh RUN chmod 755 /*.sh diff --git a/adduser.sh b/adduser.sh new file mode 100755 index 0000000..add5df2 --- /dev/null +++ b/adduser.sh @@ -0,0 +1,74 @@ +#!/bin/bash + +usage() { + echo "Usage: adduser -p -u -c -f " >&2 +} + +TEMP=`getopt -o c:f:p:u: --long comment:flow:port:,user: -n "$0" -- $@` +if [ $? != 0 ] ; then usage; exit 1 ; fi + +eval set -- "$TEMP" +while true ; do + case "$1" in + -c|--comment) + comment="$2" + shift 2 + ;; + -f|flow) + flow="$2" + shift 2 + ;; + -p|--port) + port="$2" + shift 2 + ;; + -u|--user) + user="$2" + shift 2 + ;; + --) + shift + break + ;; + *) + echo "Unknown option: $1" >&2 + usage; + exit 1 + ;; + esac +done + +if [ -z "${port}" ]; then + echo "Error: port undefined." >&2 + usage + exit 1 ; +fi + +IFS=':' +uopt=(${user}) +uopt=(${uopt[@]}) + +uid="${uopt[0]}" +level="${uopt[1]}" +email="${uopt[2]}" + +if [ -z "${uid}" ]; then + echo "Error: Undefined UID \"$user\"" >&2 + echo "Correct user format: user=[:level:email]" >&2 + echo "Like: user=myid:0:me@g.cn" >&2 + echo "Like: user=myid::me@g.cn" >&2 + echo "Like: user=myid:0" >&2 + echo "Like: user=myid" >&2 + exit 1 +fi + +if [ -z "${level}" ]; then + level=0 +fi + +if [ -z "${email}" ]; then + email="${uid}@${comment}" +fi + +jq --arg port "${port}" --arg uid "${uid}" --arg level "${level}" --arg email "${email}" --arg flow "${flow}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .settings.clients ) += [ {"id":$uid, "flow":$flow, "level":($level|tonumber), "email":$email} ] ' \ diff --git a/addusertj.sh b/addusertj.sh new file mode 100755 index 0000000..6a81457 --- /dev/null +++ b/addusertj.sh @@ -0,0 +1,74 @@ +#!/bin/bash + +usage() { + echo "Usage: adduser -p -u -c -f " >&2 +} + +TEMP=`getopt -o c:f:p:u: --long comment:flow:port:,user: -n "$0" -- $@` +if [ $? != 0 ] ; then usage; exit 1 ; fi + +eval set -- "$TEMP" +while true ; do + case "$1" in + -c|--comment) + comment="$2" + shift 2 + ;; + -f|flow) + flow="$2" + shift 2 + ;; + -p|--port) + port="$2" + shift 2 + ;; + -u|--user) + user="$2" + shift 2 + ;; + --) + shift + break + ;; + *) + echo "Unknown option: $1" >&2 + usage; + exit 1 + ;; + esac +done + +if [ -z "${port}" ]; then + echo "Error: port undefined." >&2 + usage + exit 1 ; +fi + +IFS=':' +uopt=(${user}) +uopt=(${uopt[@]}) + +psw="${uopt[0]}" +level="${uopt[1]}" +email="${uopt[2]}" + +if [ -z "${uid}" ]; then + echo "Error: Undefined UID \"$user\"" >&2 + echo "Correct user format: user=[:level:email]" >&2 + echo "Like: user=mypw:0:me@g.cn" >&2 + echo "Like: user=mypw::me@g.cn" >&2 + echo "Like: user=mypw:0" >&2 + echo "Like: user=mypw" >&2 + exit 1 +fi + +if [ -z "${level}" ]; then + level=0 +fi + +if [ -z "${email}" ]; then + email="${uid}@${comment}" +fi + +jq --arg port "${port}" --arg psw "${psw}" --arg level "${level}" --arg email "${email}" --arg flow "${flow}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .settings.clients ) += [ {"password":$psw, "flow":$flow, "level":($level|tonumber), "email":$email} ] ' \ diff --git a/fallback.sh b/fallback.sh new file mode 100755 index 0000000..90b87f3 --- /dev/null +++ b/fallback.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +usage() { + echo "Usage: fallback -p -f " >&2 +} + +TEMP=`getopt -o f:p: --long port:,fallback: -n "$0" -- $@` +if [ $? != 0 ] ; then usage; exit 1 ; fi + +eval set -- "$TEMP" +while true ; do + case "$1" in + -p|--port) + port="$2" + shift 2 + ;; + -f|--fallback) + fallback="$2" + shift 2 + ;; + --) + shift + break + ;; + *) + echo "Unknown option: $1" >&2 + usage; + exit 1 + ;; + esac +done + +if [ -z "${port}" ]; then + echo "Error: port undefined." >&2 + usage + exit 1 ; +fi + +if [ -z "${fallback}" ]; then + echo "Error: fallback undefined." >&2 + usage + exit 1 ; +fi + +IFS=':' +fopt=(${fallback}) +fopt=(${fopt[@]}) + +fhost="${fopt[0]}" +fport="${fopt[1]}" +fpath="${fopt[2]}" +fdest=$fhost:$fport + +if [ -z "${fport}" ]; then + echo "Incorrect fallback format: ${fallback}" + echo "Correct fallback: fallback=[host]<:port>[:path]" + echo "Like: fallback=baidu.com:443:/path" + echo "Like: fallback=:1443:/path" + 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 + +jq --arg port "${port}" --argjson jfallback "$Jfallback" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .settings.fallbacks ) += [ $jfallback ] ' \ diff --git a/run.sh b/run.sh index 3c10986..0dc14b0 100755 --- a/run.sh +++ b/run.sh @@ -9,37 +9,38 @@ XCONF=/tmp/server-xray.json usage() { echo "server-xray " - echo " --lx [p=443,]d=domain.com,u=id[:level[:email]]" - echo " --ls [p=443,]d=domain.com,u=id[:level[:email]]" - echo " --ms [p=443,]d=domain.com,u=id[:level[:email]]" - echo " --ts [p=443,]d=domain.com,u=psw[:level[:email]]" - echo " --lsg [p=443,]d=domain.com,u=id[:level[:email]],s=svcname" - echo " --lss [p=443,]d=domain.com,u=id[:level[:email]],w=/webpath" - echo " --lsw [p=443,]d=domain.com,u=id[:level[:email]],w=/wspath" - echo " --msw [p=443,]d=domain.com,u=id[:level[:email]],w=/wspath" - echo " --tsw [p=443,]d=domain.com,u=psw[:level[:email]],w=/wspath" - echo " --lpg [p=443,]u=id[:level[:email]],s=svcname" - echo " --lps [p=443,]u=id[:level[:email]],w=/webpath" - echo " --lpw [p=443,]u=id[:level[:email]],w=/wspath" - echo " --mpw [p=443,]u=id[:level[:email]],w=/wspath" - echo " --tpw [p=443,]u=psw[:level[:email]],w=/wspath" - echo " --ng-opt [p=443,]d=domain0.com[,d=domain1.com][...]" - echo " --ng-proxy [d=domain0.com,][d=domain1.com,]p=port-backend,l=location,n=ws|grpc|splt" - echo " --domain-block Add a domain rule for routing block, like geosite:category-ads-all" - echo " --ip-block Add a ip-addr rule for routing block, like geoip:private" - echo " --cn-block Add routing rules to avoid domains and IPs located in China being proxied" - echo " -u|--user u=id0[:level[:email]][,u=id1][...]" - echo " -k|--hook DDNS update or notifing URL to be hit" - echo " -r|--request-domain Domain name to request for letsencrypt cert" - echo " -c|--cert-home Reading TLS certs from folder //" - echo " -i|--stdin Read config from STDIN instead of auto generation" - echo " -j|--json '{"log":{"loglevel":"info"}' Json snippet to merge into the config" - echo " -d|--debug Start in debug mode with verbose output" + echo " --lgp p=11443,u=id1,u=id2...,s=svcname" + echo " --lgr p=12443,u=id1,u=id2...,s=svcname,d=dest.com,pub=xxx,prv=yyy" + echo " --lgt p=13443,u=id1,u=id2...,s=svcname,d=domain.com" + echo " --lsp p=14443,u=id1,u=id2...,w=/webpath" + echo " --lst p=16443,u=id1,u=id2...,w=/webpath,d=domain.com" + echo " --ltr p=17443,u=id1,u=id2...,[xtls],d=dest.com,pub=xxx,prv=yyy" + echo " --ltt p=18443,u=id1,u=id2...,[xtls],d=domain.com" + echo " --lwp p=19443,u=id1,u=id2...,w=/wskpath" + echo " --lwt p=22443,u=id1,u=id2...,w=/wskpath,d=domain.com" + echo " --mtt p=23443,u=id1,u=id2...,d=domain.com" + echo " --mwp p=24443,u=id1,u=id2...,w=/wskpath" + echo " --mwt p=25443,u=id1,u=id2...,w=/wskpath,d=domain.com" + echo " --ttt p=26443,u=pw1,u=pw2...,d=domain.com" + echo " --twp p=27443,u=pw1,u=pw2...,w=/wskpath" + echo " --twt p=28443,u=pw1,u=pw2...,w=/wskpath,d=domain.com" + echo " --ng-opt p=443,d=domain0.com,d=domain1.com..." + echo " --ng-proxy d=domain0.com,d=domain1.com,p=port-backend,l=location,n=ws|grpc|splt" + echo " --domain-block Add a domain rule for routing block, like geosite:category-ads-all" + echo " --ip-block Add a ip-addr rule for routing block, like geoip:private" + echo " --cn-block Add routing rules to avoid domains and IPs located in China being proxied" + echo " -u|--user u=id0,u=id1..." + echo " -k|--hook DDNS update or notifing URL to be hit" + echo " -r|--request-domain Domain name to request for letsencrypt cert" + echo " -c|--cert-home Reading TLS certs from folder //" + echo " -i|--stdin Read config from STDIN instead of auto generation" + echo " -j|--json Json snippet to merge into the config. Say '{"log":{"loglevel":"info"}'" + echo " -d|--debug Start in debug mode with verbose output" } Jrules='{"rules":[]}' -TEMP=`getopt -o u:k:r:c:j:di --long user:,hook:,request-domain:,cert-home:,ip-block:,domain-block:,cn-block,lx:,ls:,ms:,ts:,lsg:,lss:,lsw:,msw:,tsw:,lpg:,lps:,lpw:,mpw:,tpw:,ng-opt:,ng-proxy:,json:,stdin,debug -n "$0" -- $@` +TEMP=`getopt -o u:k:r:c:j:di --long user:,hook:,request-domain:,cert-home:,ip-block:,domain-block:,cn-block,lgp:,lgr:,lgt:,lsp:,lst:,ltr:,ltt:,lwp:,lwt:,mtt:,mwp:,mwt:,ttt:,twp:,twt:,ng-opt:,ng-proxy:,json:,stdin,debug -n "$0" -- $@` if [ $? != 0 ] ; then usage; exit 1 ; fi eval set -- "$TEMP" @@ -73,9 +74,9 @@ while true ; do INJECT+=("$2") shift 2 ;; - --lx|--ls|--ms|--ts|--lsg|--lss|--lsw|--msw|--tsw|--lpg|--lps|--lpw|--mpw|--tpw) + --lgp|--lgr|--lgt|--lsp|--lst|--ltr|--ltt|--lwp|--lwt|--mtt|--mwp|--mwt|--ttt|--twp|--twt) SVC=`echo $1|tr -d '\-\-'` - SVCMD+=("${DIR}server-${SVC}.sh $2") + SVCMD+=("${DIR}/server-${SVC}.sh $2") shift 2 ;; --domain-block) @@ -177,8 +178,6 @@ if [ -n "${SVCMD}" ]; then if [ "${DEBUG}" = "1" ]; then cat $XCONF |jq '.log.loglevel |="debug"' |sponge $XCONF echo - cat $XCONF - echo fi if [ -n "${NGOPT}" ]; then @@ -208,6 +207,8 @@ if [ -n "${SVCMD}" ]; then done fi + cat $XCONF + echo exec /usr/local/bin/xray -c $XCONF else diff --git a/server-lpg.sh b/server-lgp.sh similarity index 55% rename from server-lpg.sh rename to server-lgp.sh index 44f7a15..30dc440 100755 --- a/server-lpg.sh +++ b/server-lgp.sh @@ -1,39 +1,40 @@ #!/bin/bash -usage() { - echo "Usage: server-lpg ,,," -} +DIR=`dirname $0` -port=443 +usage() { + echo "VLESS-GRPC-PLAIN builder" + echo "Usage: server-lgp ,,,,..." +} 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]}" ;; + u|user) + xuser+=("${kv[1]}") + ;; + x|xconf) + xconf="${kv[1]}" + ;; esac done -if [ -z "${xconf}" ]; then - echo "Error: xconf undefined." +if [ -z "${port}" ]; then + echo "Error: port undefined." usage - exit 1 + exit 1 ; fi if [ -z "${service}" ]; then - echo "Error: service name undefined." + echo "Error: service undefined." usage exit 1 fi @@ -44,44 +45,34 @@ if [ -z "${xuser}" ]; then exit 1 fi +if [ -z "${xconf}" ]; then + echo "Error: xconf 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 # Remove existing port number if existing. cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $XCONF -cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"vless", "settings":{"clients":[]}}]' |sponge $XCONF +# Add inbound element +cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"vless", "settings":{"clients":[]}}]' |sponge $XCONF +cat $XCONF |jq --arg port "${port}" '( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' |sponge $XCONF + +# User settings 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=[:level:email]" - echo "Like: user=myid:0:me@g.cn" - echo "Like: user=myid::me@g.cn" - echo "Like: user=myid:0" - echo "Like: user=myid" - exit 1 - fi - if [ -z "${uopt[1]}" ]; then - uopt[1]=0 - 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 + cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c lgp.$domain $flowopt | 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}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"grpc", "security":"none" } ' \ -|sponge $XCONF - +# Network settings cat $XCONF |jq --arg port "${port}" --arg service "${service}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"grpcSettings":{"serviceName":$service}} ' \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"grpc","grpcSettings":{"serviceName":$service} } ' \ +|sponge $XCONF + +# Plain settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"none" } ' \ |sponge $XCONF diff --git a/server-lgr.sh b/server-lgr.sh new file mode 100755 index 0000000..595003c --- /dev/null +++ b/server-lgr.sh @@ -0,0 +1,134 @@ +#!/bin/bash + +DIR=`dirname $0` + +usage() { + echo "VLESS-GRPC-REALITY builder" + echo "Usage: server-lgr ,,,,[xtls],,[pub=xxx,prv=yyy],,..." +} + +options=(`echo $1 |tr ',' ' '`) +for option in "${options[@]}" +do + kv=(`echo $option |tr '=' ' '`) + case "${kv[0]}" in + c|certhome) + certhome="${kv[1]}" + ;; + d|dest) + dest="${kv[1]}" + ;; + f|fallback) + fallback+=("${kv[1]}") + ;; + flow) + flow="${kv[1]}" + ;; + p|port) + port="${kv[1]}" + ;; + s|service) + service="${kv[1]}" + ;; + shortId) + shortIds+=("${kv[1]}") + ;; + prv|privateKey) + prvkey="${kv[1]}" + ;; + pub|publicKey) + pubkey="${kv[1]}" + ;; + u|user) + xuser+=("${kv[1]}") + ;; + x|xconf) + xconf="${kv[1]}" + ;; + xtls) + flow="xtls-rprx-vision" + ;; + esac +done + +if [ -z "${dest}" ]; then + echo "Error: dest undefined." + usage + exit 1 +fi + +if [ -n "${flow}" ]; then + flowopt="-f ${flow}" +fi + +if [ -z "${port}" ]; then + echo "Error: port undefined." + usage + exit 1 ; +fi + +if [ -z "${service}" ]; then + echo "Error: service undefined." + usage + exit 1 +fi + +if [ -z "${xuser}" ]; then + echo "Error: user undefined." + usage + exit 1 +fi + +if [ -z "${xconf}" ]; then + echo "Error: xconf undefined." + usage + exit 1 +fi + +if [ -z "${prvkey}" ] || [ -z "${pubkey}" ] ; then + echo "Warning: PublicKey / PrivateKey undefined, Generated new..." + kv=(`/usr/local/bin/xray x25519|cut -d ' ' -f3|tr ' '`) + prvkey="${kv[0]}" + pubkey="${kv[1]}" + echo "PublicKey: $pubkey" +fi + +if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi + +XCONF=$xconf +# Remove existing port number if existing. +cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $XCONF + +# Add inbound element +cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"vless", "settings":{"clients":[]}}]' |sponge $XCONF +cat $XCONF |jq --arg port "${port}" '( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' |sponge $XCONF + +# User settings +for xu in "${xuser[@]}" +do + cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c lgr.$dest $flowopt | sponge $XCONF +done + +# Fallback settings +for fb in "${fallback[@]}" +do + cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF +done + +# Network settings +cat $XCONF |jq --arg port "${port}" --arg service "${service}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"grpc","grpcSettings":{"serviceName":$service} } ' \ +|sponge $XCONF + +# Reality settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"reality"} ' \ +|sponge $XCONF + +cat $XCONF |jq --arg port "${port}" --arg dest "${dest}" --arg pubkey "${pubkey}" --arg prvkey "${prvkey}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"realitySettings":{"show":true,"dest":"\($dest):443","serverNames":[$dest,""],"privateKey":$prvkey,"publicKey":$pubkey,"shortIds":[""]} } ' \ +|sponge $XCONF + +cat $XCONF |jq '( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings.realitySettings.shortIds ) +=$ARGS.positional' \ +--arg port "${port}" --args ${shortIds[@]} \ +|sponge $XCONF diff --git a/server-lsg.sh b/server-lgt.sh similarity index 65% rename from server-lsg.sh rename to server-lgt.sh index c0e1423..3dc5c6e 100755 --- a/server-lsg.sh +++ b/server-lgt.sh @@ -1,7 +1,10 @@ #!/bin/bash +DIR=`dirname $0` + usage() { - echo "Usage: server-lsg ,,,,," + echo "VLESS-GRPC-TLS builder" + echo "Usage: server-lgt ,,,,[xtls],,,..." } options=(`echo $1 |tr ',' ' '`) @@ -9,24 +12,33 @@ for option in "${options[@]}" do kv=(`echo $option |tr '=' ' '`) case "${kv[0]}" in - x|xconf) - xconf="${kv[1]}" - ;; c|certhome) certhome="${kv[1]}" ;; - p|port) - port="${kv[1]}" - ;; d|domain) domain="${kv[1]}" ;; - u|user) - xuser+=("${kv[1]}") + f|fallback) + fallback+=("${kv[1]}") + ;; + flow) + flow="${kv[1]}" + ;; + p|port) + port="${kv[1]}" ;; s|service) service="${kv[1]}" ;; + u|user) + xuser+=("${kv[1]}") + ;; + x|xconf) + xconf="${kv[1]}" + ;; + xtls) + flow="xtls-rprx-vision" + ;; esac done @@ -36,18 +48,24 @@ if [ -z "${certhome}" ]; then exit 1 fi -if [ -z "${xconf}" ]; then - echo "Error: xconf undefined." +if [ -z "${domain}" ]; then + echo "Error: domain undefined." usage exit 1 fi -if [ -z "${port}" ]; then - port=443 +if [ -n "${flow}" ]; then + flowopt="-f ${flow}" fi -if [ -z "${domain}" ]; then - echo "Error: domain undefined." +if [ -z "${port}" ]; then + echo "Error: port undefined." + usage + exit 1 ; +fi + +if [ -z "${service}" ]; then + echo "Error: service undefined." usage exit 1 fi @@ -58,47 +76,11 @@ if [ -z "${xuser}" ]; then exit 1 fi -if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi - -XCONF=$xconf -# Remove existing port number if existing. -cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $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=[:level:email]" - echo "Like: user=myid:0:me@g.cn" - echo "Like: user=myid::me@g.cn" - echo "Like: user=myid:0" - echo "Like: user=myid" - exit 1 - fi - if [ -z "${uopt[1]}" ]; then - uopt[1]=0 - 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":"tls"} ' \ -|sponge $XCONF - -cat $XCONF |jq --arg port "${port}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{"alpn":["http/2"]}} ' \ -|sponge $XCONF +if [ -z "${xconf}" ]; then + echo "Error: xconf undefined." + usage + exit 1 +fi if [ -f "${certhome}/${domain}/fullchain.cer" ] && [ -f "${certhome}/${domain}/${domain}.key" ]; then fullchain="${certhome}/${domain}/fullchain.cer" @@ -111,6 +93,42 @@ if [ ! -f "${fullchain}" ] || [ ! -f "${prvkey}" ]; then exit 2 fi +if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi + +XCONF=$xconf +# Remove existing port number if existing. +cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $XCONF + +# Add inbound element +cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"vless", "settings":{"clients":[]}}]' |sponge $XCONF +cat $XCONF |jq --arg port "${port}" '( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' |sponge $XCONF + +# User settings +for xu in "${xuser[@]}" +do + cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c lgt.$domain $flowopt | sponge $XCONF +done + +# Fallback settings +for fb in "${fallback[@]}" +do + cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF +done + +# Network settings +cat $XCONF |jq --arg port "${port}" --arg service "${service}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"grpc","grpcSettings":{"serviceName":$service} } ' \ +|sponge $XCONF + +# TLS settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"tls"} ' \ +|sponge $XCONF + +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{}} ' \ +|sponge $XCONF + cat $XCONF |jq --arg port "${port}" --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ '( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings.tlsSettings ) += {"certificates":[{"certificateFile":$fullchain, "keyFile":$prvkey}]} ' \ |sponge $XCONF diff --git a/server-lps.sh b/server-lps.sh deleted file mode 100755 index 7895d98..0000000 --- a/server-lps.sh +++ /dev/null @@ -1,129 +0,0 @@ -#!/bin/bash - -usage() { - echo "Usage: server-lps ,,," -} - -port=443 - -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) - webpath="${kv[1]}" - ;; - f|fallback) - fallback+=("${kv[1]}") - ;; - esac -done - -if [ -z "${xconf}" ]; then - echo "Error: xconf undefined." - usage - exit 1 -fi - -if [ -z "${xuser}" ]; then - echo "Error: user undefined." - usage - exit 1 -fi - -if [ -z "${webpath}" ]; then - echo "Error: webpath 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 -# Remove existing port number if existing. -cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $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=[:level:email]" - echo "Like: user=myid:0:me@g.cn" - echo "Like: user=myid::me@g.cn" - echo "Like: user=myid:0" - echo "Like: user=myid" - exit 1 - fi - if [ -z "${uopt[1]}" ]; then - uopt[1]=0 - 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":"splithttp", "security":"none" } ' \ -|sponge $XCONF - -cat $XCONF |jq --arg port "${port}" --arg webpath "${webpath}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"splithttpSettings":{"path":$webpath}} ' \ -|sponge $XCONF diff --git a/server-lpw.sh b/server-lpw.sh deleted file mode 100755 index f3d9b7d..0000000 --- a/server-lpw.sh +++ /dev/null @@ -1,129 +0,0 @@ -#!/bin/bash - -usage() { - echo "Usage: server-lpw ,,," -} - -port=443 - -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 "${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 -# Remove existing port number if existing. -cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $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=[:level:email]" - echo "Like: user=myid:0:me@g.cn" - echo "Like: user=myid::me@g.cn" - echo "Like: user=myid:0" - echo "Like: user=myid" - exit 1 - fi - if [ -z "${uopt[1]}" ]; then - uopt[1]=0 - 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 diff --git a/server-ls.sh b/server-ls.sh deleted file mode 100755 index 127ed52..0000000 --- a/server-ls.sh +++ /dev/null @@ -1,155 +0,0 @@ -#!/bin/bash - -usage() { - echo "Usage: server-ls ,,,," -} - -options=(`echo $1 |tr ',' ' '`) -for option in "${options[@]}" -do - kv=(`echo $option |tr '=' ' '`) - case "${kv[0]}" in - x|xconf) - xconf="${kv[1]}" - ;; - c|certhome) - certhome="${kv[1]}" - ;; - p|port) - port="${kv[1]}" - ;; - d|domain) - domain="${kv[1]}" - ;; - u|user) - xuser+=("${kv[1]}") - ;; - f|fallback) - fallback+=("${kv[1]}") - ;; - esac -done - -if [ -z "${certhome}" ]; then - echo "Error: certhome undefined." - usage - exit 1 -fi - -if [ -z "${xconf}" ]; then - echo "Error: xconf 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 [ -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 -# Remove existing port number if existing. -cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $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=[:level:email]" - echo "Like: user=myid:0:me@g.cn" - echo "Like: user=myid::me@g.cn" - echo "Like: user=myid:0" - echo "Like: user=myid" - exit 1 - fi - if [ -z "${uopt[1]}" ]; then - uopt[1]=0 - 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":"tcp", "security":"tls" } ' \ -|sponge $XCONF - -cat $XCONF |jq --arg port "${port}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{"alpn":["http/1.1"]} } ' \ -|sponge $XCONF - -if [ -f "${certhome}/${domain}/fullchain.cer" ] && [ -f "${certhome}/${domain}/${domain}.key" ]; then - fullchain="${certhome}/${domain}/fullchain.cer" - prvkey="${certhome}/${domain}/${domain}.key" -fi - -if [ ! -f "${fullchain}" ] || [ ! -f "${prvkey}" ]; then - echo "TLS cert missing?" - echo "Abort." - exit 2 -fi - -cat $XCONF |jq --arg port "${port}" --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings.tlsSettings ) += {"certificates":[{"certificateFile":$fullchain, "keyFile":$prvkey}]} ' \ -|sponge $XCONF diff --git a/server-lsp.sh b/server-lsp.sh new file mode 100755 index 0000000..3e43a08 --- /dev/null +++ b/server-lsp.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +DIR=`dirname $0` + +usage() { + echo "VLESS-SPLT-PLAIN builder" + echo "Usage: server-lsp ,,,,..." +} + +options=(`echo $1 |tr ',' ' '`) +for option in "${options[@]}" +do + kv=(`echo $option |tr '=' ' '`) + case "${kv[0]}" in + p|port) + port="${kv[1]}" + ;; + u|user) + xuser+=("${kv[1]}") + ;; + w|wpath) + webpath="${kv[1]}" + ;; + x|xconf) + xconf="${kv[1]}" + ;; + esac +done + +if [ -z "${port}" ]; then + echo "Error: port undefined." + usage + exit 1 ; +fi + +if [ -z "${webpath}" ]; then + echo "Error: webpath undefined." + usage + exit 1 +fi + +if [ -z "${xuser}" ]; then + echo "Error: user undefined." + usage + exit 1 +fi + +if [ -z "${xconf}" ]; then + echo "Error: xconf 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 +# Remove existing port number if existing. +cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $XCONF + +# Add inbound element +cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"vless", "settings":{"clients":[]}}]' |sponge $XCONF +cat $XCONF |jq --arg port "${port}" '( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' |sponge $XCONF + +# User settings +for xu in "${xuser[@]}" +do + cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c lsp.$domain $flowopt | sponge $XCONF +done + +# Network settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"splithttp","splithttpSettings":{"path":$webpath}} ' \ +|sponge $XCONF + +# Plain settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"none" } ' \ +|sponge $XCONF diff --git a/server-lss.sh b/server-lss.sh deleted file mode 100755 index e53ba2f..0000000 --- a/server-lss.sh +++ /dev/null @@ -1,168 +0,0 @@ -#!/bin/bash - -usage() { - echo "Usage: server-lss ,,,,," -} - -options=(`echo $1 |tr ',' ' '`) -for option in "${options[@]}" -do - kv=(`echo $option |tr '=' ' '`) - case "${kv[0]}" in - x|xconf) - xconf="${kv[1]}" - ;; - c|certhome) - certhome="${kv[1]}" - ;; - p|port) - port="${kv[1]}" - ;; - d|domain) - domain="${kv[1]}" - ;; - u|user) - xuser+=("${kv[1]}") - ;; - w|wpath) - webpath="${kv[1]}" - ;; - f|fallback) - fallback+=("${kv[1]}") - ;; - esac -done - -if [ -z "${certhome}" ]; then - echo "Error: certhome undefined." - usage - exit 1 -fi - -if [ -z "${xconf}" ]; then - echo "Error: xconf 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 [ -z "${xuser}" ]; then - echo "Error: user undefined." - usage - exit 1 -fi - -if [ -z "${webpath}" ]; then - echo "Error: webpath 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 -# Remove existing port number if existing. -cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $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=[:level:email]" - echo "Like: user=myid:0:me@g.cn" - echo "Like: user=myid::me@g.cn" - echo "Like: user=myid:0" - echo "Like: user=myid" - exit 1 - fi - if [ -z "${uopt[1]}" ]; then - uopt[1]=0 - 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":"splithttp", "security":"tls"} ' \ -|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 webpath "${webpath}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"splithttpSettings":{"path":$webpath}} ' \ -|sponge $XCONF - -if [ -f "${certhome}/${domain}/fullchain.cer" ] && [ -f "${certhome}/${domain}/${domain}.key" ]; then - fullchain="${certhome}/${domain}/fullchain.cer" - prvkey="${certhome}/${domain}/${domain}.key" -fi - -if [ ! -f "${fullchain}" ] || [ ! -f "${prvkey}" ]; then - echo "TLS cert missing?" - echo "Abort." - exit 2 -fi - -cat $XCONF |jq --arg port "${port}" --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings.tlsSettings ) += {"certificates":[{"certificateFile":$fullchain, "keyFile":$prvkey}]} ' \ -|sponge $XCONF diff --git a/server-lst.sh b/server-lst.sh new file mode 100755 index 0000000..1ae84d1 --- /dev/null +++ b/server-lst.sh @@ -0,0 +1,134 @@ +#!/bin/bash + +DIR=`dirname $0` + +usage() { + echo "VLESS-SPLT-TLS builder" + echo "Usage: server-lst ,,,,,,..." +} + +options=(`echo $1 |tr ',' ' '`) +for option in "${options[@]}" +do + kv=(`echo $option |tr '=' ' '`) + case "${kv[0]}" in + c|certhome) + certhome="${kv[1]}" + ;; + d|domain) + domain="${kv[1]}" + ;; + f|fallback) + fallback+=("${kv[1]}") + ;; + flow) + flow="${kv[1]}" + ;; + p|port) + port="${kv[1]}" + ;; + u|user) + xuser+=("${kv[1]}") + ;; + w|wpath) + webpath="${kv[1]}" + ;; + x|xconf) + xconf="${kv[1]}" + ;; + xtls) + flow="xtls-rprx-vision" + ;; + esac +done + +if [ -z "${certhome}" ]; then + echo "Error: certhome undefined." + usage + exit 1 +fi + +if [ -z "${domain}" ]; then + echo "Error: domain undefined." + usage + exit 1 +fi + +if [ -n "${flow}" ]; then + flowopt="-f ${flow}" +fi + +if [ -z "${port}" ]; then + echo "Error: port undefined." + usage + exit 1 ; +fi + +if [ -z "${webpath}" ]; then + echo "Error: webpath undefined." + usage + exit 1 +fi + +if [ -z "${xuser}" ]; then + echo "Error: user undefined." + usage + exit 1 +fi + +if [ -z "${xconf}" ]; then + echo "Error: xconf undefined." + usage + exit 1 +fi + +if [ -f "${certhome}/${domain}/fullchain.cer" ] && [ -f "${certhome}/${domain}/${domain}.key" ]; then + fullchain="${certhome}/${domain}/fullchain.cer" + prvkey="${certhome}/${domain}/${domain}.key" +fi + +if [ ! -f "${fullchain}" ] || [ ! -f "${prvkey}" ]; then + echo "TLS cert missing?" + echo "Abort." + exit 2 +fi + +if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi + +XCONF=$xconf +# Remove existing port number if existing. +cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $XCONF + +# Add inbound element +cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"vless", "settings":{"clients":[]}}]' |sponge $XCONF +cat $XCONF |jq --arg port "${port}" '( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' |sponge $XCONF + +# User settings +for xu in "${xuser[@]}" +do + cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c lst.$domain $flowopt | sponge $XCONF +done + +# Fallback settings +for fb in "${fallback[@]}" +do + cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF +done + +# Network settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"splithttp","splithttpSettings":{"path":$webpath}} ' \ +|sponge $XCONF + +# TLS settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"tls"} ' \ +|sponge $XCONF + +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{}} ' \ +|sponge $XCONF + +cat $XCONF |jq --arg port "${port}" --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings.tlsSettings ) += {"certificates":[{"certificateFile":$fullchain, "keyFile":$prvkey}]} ' \ +|sponge $XCONF diff --git a/server-ltr.sh b/server-ltr.sh new file mode 100755 index 0000000..770402e --- /dev/null +++ b/server-ltr.sh @@ -0,0 +1,125 @@ +#!/bin/bash + +DIR=`dirname $0` + +usage() { + echo "VLESS-TCP-REALITY builder" + echo "Usage: server-ltr ,,,[xtls],,[pub=xxx,prv=yyy],,..." +} + +options=(`echo $1 |tr ',' ' '`) +for option in "${options[@]}" +do + kv=(`echo $option |tr '=' ' '`) + case "${kv[0]}" in + c|certhome) + certhome="${kv[1]}" + ;; + d|dest) + dest="${kv[1]}" + ;; + f|fallback) + fallback+=("${kv[1]}") + ;; + flow) + flow="${kv[1]}" + ;; + p|port) + port="${kv[1]}" + ;; + shortId) + shortIds+=("${kv[1]}") + ;; + prv|privateKey) + prvkey="${kv[1]}" + ;; + pub|publicKey) + pubkey="${kv[1]}" + ;; + u|user) + xuser+=("${kv[1]}") + ;; + x|xconf) + xconf="${kv[1]}" + ;; + xtls) + flow="xtls-rprx-vision" + ;; + esac +done + +if [ -z "${dest}" ]; then + echo "Error: dest undefined." + usage + exit 1 +fi + +if [ -n "${flow}" ]; then + flowopt="-f ${flow}" +fi + +if [ -z "${port}" ]; then + echo "Error: port undefined." + usage + exit 1 ; +fi + +if [ -z "${xuser}" ]; then + echo "Error: user undefined." + usage + exit 1 +fi + +if [ -z "${xconf}" ]; then + echo "Error: xconf undefined." + usage + exit 1 +fi + +if [ -z "${prvkey}" ] || [ -z "${pubkey}" ] ; then + echo "Warning: PublicKey / PrivateKey undefined, Generated new..." + kv=(`/usr/local/bin/xray x25519|cut -d ' ' -f3|tr ' '`) + prvkey="${kv[0]}" + pubkey="${kv[1]}" + echo "PublicKey: $pubkey" +fi + +if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi + +XCONF=$xconf +# Remove existing port number if existing. +cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $XCONF + +# Add inbound element +cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"vless", "settings":{"clients":[]}}]' |sponge $XCONF +cat $XCONF |jq --arg port "${port}" '( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' |sponge $XCONF + +# User settings +for xu in "${xuser[@]}" +do + cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c ltr.$dest $flowopt | sponge $XCONF +done + +# Fallback settings +for fb in "${fallback[@]}" +do + cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF +done + +# Network settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"tcp"} ' \ +|sponge $XCONF + +# Reality settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"reality"} ' \ +|sponge $XCONF + +cat $XCONF |jq --arg port "${port}" --arg dest "${dest}" --arg pubkey "${pubkey}" --arg prvkey "${prvkey}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"realitySettings":{"show":true,"dest":"\($dest):443","serverNames":[$dest,""],"privateKey":$prvkey,"publicKey":$pubkey,"shortIds":[""]} } ' \ +|sponge $XCONF + +cat $XCONF |jq '( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings.realitySettings.shortIds ) +=$ARGS.positional' \ +--arg port "${port}" --args ${shortIds[@]} \ +|sponge $XCONF diff --git a/server-lx.sh b/server-ltsx.sh similarity index 100% rename from server-lx.sh rename to server-ltsx.sh diff --git a/server-ltt.sh b/server-ltt.sh new file mode 100755 index 0000000..8e85da3 --- /dev/null +++ b/server-ltt.sh @@ -0,0 +1,125 @@ +#!/bin/bash + +DIR=`dirname $0` + +usage() { + echo "VLESS-TCP-TLS builder" + echo "Usage: server-ltt ,,,[xtls],,,..." +} + +options=(`echo $1 |tr ',' ' '`) +for option in "${options[@]}" +do + kv=(`echo $option |tr '=' ' '`) + case "${kv[0]}" in + c|certhome) + certhome="${kv[1]}" + ;; + d|domain) + domain="${kv[1]}" + ;; + f|fallback) + fallback+=("${kv[1]}") + ;; + flow) + flow="${kv[1]}" + ;; + p|port) + port="${kv[1]}" + ;; + u|user) + xuser+=("${kv[1]}") + ;; + x|xconf) + xconf="${kv[1]}" + ;; + xtls) + flow="xtls-rprx-vision" + ;; + esac +done + +if [ -z "${certhome}" ]; then + echo "Error: certhome undefined." + usage + exit 1 +fi + +if [ -z "${domain}" ]; then + echo "Error: domain undefined." + usage + exit 1 +fi + +if [ -n "${flow}" ]; then + flowopt="-f ${flow}" +fi + +if [ -z "${port}" ]; then + echo "Error: port undefined." + usage + exit 1 ; +fi + +if [ -z "${xuser}" ]; then + echo "Error: user undefined." + usage + exit 1 +fi + +if [ -z "${xconf}" ]; then + echo "Error: xconf undefined." + usage + exit 1 +fi + +if [ -f "${certhome}/${domain}/fullchain.cer" ] && [ -f "${certhome}/${domain}/${domain}.key" ]; then + fullchain="${certhome}/${domain}/fullchain.cer" + prvkey="${certhome}/${domain}/${domain}.key" +fi + +if [ ! -f "${fullchain}" ] || [ ! -f "${prvkey}" ]; then + echo "TLS cert missing?" + echo "Abort." + exit 2 +fi + +if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi + +XCONF=$xconf +# Remove existing port number if existing. +cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $XCONF + +# Add inbound element +cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"vless", "settings":{"clients":[]}}]' |sponge $XCONF +cat $XCONF |jq --arg port "${port}" '( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' |sponge $XCONF + +# User settings +for xu in "${xuser[@]}" +do + cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c ltt.$dest $flowopt | sponge $XCONF +done + +# Fallback settings +for fb in "${fallback[@]}" +do + cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF +done + +# Network settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"tcp"} ' \ +|sponge $XCONF + +# TLS settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"tls"} ' \ +|sponge $XCONF + +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{}} ' \ +|sponge $XCONF + +cat $XCONF |jq --arg port "${port}" --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings.tlsSettings ) += {"certificates":[{"certificateFile":$fullchain, "keyFile":$prvkey}]} ' \ +|sponge $XCONF diff --git a/server-lwp.sh b/server-lwp.sh new file mode 100755 index 0000000..6c2f010 --- /dev/null +++ b/server-lwp.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +DIR=`dirname $0` + +usage() { + echo "VLESS-WS-PLAIN builder" + echo "Usage: server-lwp ,,,,..." +} + +options=(`echo $1 |tr ',' ' '`) +for option in "${options[@]}" +do + kv=(`echo $option |tr '=' ' '`) + case "${kv[0]}" in + p|port) + port="${kv[1]}" + ;; + u|user) + xuser+=("${kv[1]}") + ;; + w|wpath) + webpath="${kv[1]}" + ;; + x|xconf) + xconf="${kv[1]}" + ;; + esac +done + +if [ -z "${port}" ]; then + echo "Error: port undefined." + usage + exit 1 ; +fi + +if [ -z "${wspath}" ]; then + echo "Error: wspath undefined." + usage + exit 1 +fi + +if [ -z "${xuser}" ]; then + echo "Error: user undefined." + usage + exit 1 +fi + +if [ -z "${xconf}" ]; then + echo "Error: xconf 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 +# Remove existing port number if existing. +cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $XCONF + +# Add inbound element +cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"vless", "settings":{"clients":[]}}]' |sponge $XCONF +cat $XCONF |jq --arg port "${port}" '( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' |sponge $XCONF + +# User settings +for xu in "${xuser[@]}" +do + cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c lwp.$domain $flowopt | sponge $XCONF +done + +# Network settings +cat $XCONF |jq --arg port "${port}" --arg wspath "${wspath}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"ws","wsSettings":{"path":$wspath}}' \ +|sponge $XCONF + +# Plain settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"none" } ' \ +|sponge $XCONF diff --git a/server-lsw.sh b/server-lwt.sh similarity index 50% rename from server-lsw.sh rename to server-lwt.sh index cdafa57..4238420 100755 --- a/server-lsw.sh +++ b/server-lwt.sh @@ -1,7 +1,10 @@ #!/bin/bash +DIR=`dirname $0` + usage() { - echo "Usage: server-lsw ,,,,," + echo "VLESS-WS-TLS builder" + echo "Usage: server-lwt ,,,,,,..." } options=(`echo $1 |tr ',' ' '`) @@ -9,26 +12,32 @@ for option in "${options[@]}" do kv=(`echo $option |tr '=' ' '`) case "${kv[0]}" in - x|xconf) - xconf="${kv[1]}" - ;; c|certhome) certhome="${kv[1]}" ;; - p|port) - port="${kv[1]}" - ;; d|domain) domain="${kv[1]}" ;; + f|fallback) + fallback+=("${kv[1]}") + ;; + flow) + flow="${kv[1]}" + ;; + p|port) + port="${kv[1]}" + ;; u|user) xuser+=("${kv[1]}") ;; w|wpath) wspath="${kv[1]}" ;; - f|fallback) - fallback+=("${kv[1]}") + x|xconf) + xconf="${kv[1]}" + ;; + xtls) + flow="xtls-rprx-vision" ;; esac done @@ -39,18 +48,24 @@ if [ -z "${certhome}" ]; then exit 1 fi -if [ -z "${xconf}" ]; then - echo "Error: xconf undefined." +if [ -z "${domain}" ]; then + echo "Error: domain undefined." usage exit 1 fi -if [ -z "${port}" ]; then - port=443 +if [ -n "${flow}" ]; then + flowopt="-f ${flow}" fi -if [ -z "${domain}" ]; then - echo "Error: domain undefined." +if [ -z "${port}" ]; then + echo "Error: port undefined." + usage + exit 1 ; +fi + +if [ -z "${wspath}" ]; then + echo "Error: wspath undefined." usage exit 1 fi @@ -61,97 +76,12 @@ if [ -z "${xuser}" ]; then exit 1 fi -if [ -z "${wspath}" ]; then - echo "Error: wspath undefined." +if [ -z "${xconf}" ]; then + echo "Error: xconf 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 -# Remove existing port number if existing. -cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $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=[:level:email]" - echo "Like: user=myid:0:me@g.cn" - echo "Like: user=myid::me@g.cn" - echo "Like: user=myid:0" - echo "Like: user=myid" - exit 1 - fi - if [ -z "${uopt[1]}" ]; then - uopt[1]=0 - 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":"tls"} ' \ -|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 - if [ -f "${certhome}/${domain}/fullchain.cer" ] && [ -f "${certhome}/${domain}/${domain}.key" ]; then fullchain="${certhome}/${domain}/fullchain.cer" prvkey="${certhome}/${domain}/${domain}.key" @@ -163,6 +93,42 @@ if [ ! -f "${fullchain}" ] || [ ! -f "${prvkey}" ]; then exit 2 fi +if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi + +XCONF=$xconf +# Remove existing port number if existing. +cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $XCONF + +# Add inbound element +cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"vless", "settings":{"clients":[]}}]' |sponge $XCONF +cat $XCONF |jq --arg port "${port}" '( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' |sponge $XCONF + +# User settings +for xu in "${xuser[@]}" +do + cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c lwt.$domain $flowopt | sponge $XCONF +done + +# Fallback settings +for fb in "${fallback[@]}" +do + cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF +done + +# Network settings +cat $XCONF |jq --arg port "${port}" --arg wspath "${wspath}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"ws","wsSettings":{"path":$wspath}}' \ +|sponge $XCONF + +# TLS settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"tls"} ' \ +|sponge $XCONF + +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{}} ' \ +|sponge $XCONF + cat $XCONF |jq --arg port "${port}" --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ '( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings.tlsSettings ) += {"certificates":[{"certificateFile":$fullchain, "keyFile":$prvkey}]} ' \ |sponge $XCONF diff --git a/server-mpw.sh b/server-mpw.sh deleted file mode 100755 index d654b00..0000000 --- a/server-mpw.sh +++ /dev/null @@ -1,129 +0,0 @@ -#!/bin/bash - -usage() { - echo "Usage: server-mpw ,,," -} - -port=443 - -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 "${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 -# Remove existing port number if existing. -cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $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=[:level:email]" - echo "Like: user=myid:0:me@g.cn" - echo "Like: user=myid::me@g.cn" - echo "Like: user=myid:0" - echo "Like: user=myid" - exit 1 - fi - if [ -z "${uopt[1]}" ]; then - uopt[1]=0 - 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 diff --git a/server-ms.sh b/server-ms.sh deleted file mode 100755 index cd5a96c..0000000 --- a/server-ms.sh +++ /dev/null @@ -1,155 +0,0 @@ -#!/bin/bash - -usage() { - echo "Usage: server-ms ,,,," -} - -options=(`echo $1 |tr ',' ' '`) -for option in "${options[@]}" -do - kv=(`echo $option |tr '=' ' '`) - case "${kv[0]}" in - x|xconf) - xconf="${kv[1]}" - ;; - c|certhome) - certhome="${kv[1]}" - ;; - p|port) - port="${kv[1]}" - ;; - d|domain) - domain="${kv[1]}" - ;; - u|user) - xuser+=("${kv[1]}") - ;; - f|fallback) - fallback+=("${kv[1]}") - ;; - esac -done - -if [ -z "${certhome}" ]; then - echo "Error: certhome undefined." - usage - exit 1 -fi - -if [ -z "${xconf}" ]; then - echo "Error: xconf 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 [ -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 -# Remove existing port number if existing. -cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $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=[:level:email]" - echo "Like: user=myid:0:me@g.cn" - echo "Like: user=myid::me@g.cn" - echo "Like: user=myid:0" - echo "Like: user=myid" - exit 1 - fi - if [ -z "${uopt[1]}" ]; then - uopt[1]=0 - 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":"tcp", "security":"tls" } ' \ -|sponge $XCONF - -cat $XCONF |jq --arg port "${port}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{"alpn":["http/1.1"]} } ' \ -|sponge $XCONF - -if [ -f "${certhome}/${domain}/fullchain.cer" ] && [ -f "${certhome}/${domain}/${domain}.key" ]; then - fullchain="${certhome}/${domain}/fullchain.cer" - prvkey="${certhome}/${domain}/${domain}.key" -fi - -if [ ! -f "${fullchain}" ] || [ ! -f "${prvkey}" ]; then - echo "TLS cert missing?" - echo "Abort." - exit 2 -fi - -cat $XCONF |jq --arg port "${port}" --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings.tlsSettings ) += {"certificates":[{"certificateFile":$fullchain, "keyFile":$prvkey}]} ' \ -|sponge $XCONF diff --git a/server-mtt.sh b/server-mtt.sh new file mode 100755 index 0000000..314bfdd --- /dev/null +++ b/server-mtt.sh @@ -0,0 +1,125 @@ +#!/bin/bash + +DIR=`dirname $0` + +usage() { + echo "VMESS-TCP-TLS builder" + echo "Usage: server-mtt ,,,,,..." +} + +options=(`echo $1 |tr ',' ' '`) +for option in "${options[@]}" +do + kv=(`echo $option |tr '=' ' '`) + case "${kv[0]}" in + c|certhome) + certhome="${kv[1]}" + ;; + d|domain) + domain="${kv[1]}" + ;; + f|fallback) + fallback+=("${kv[1]}") + ;; + flow) + flow="${kv[1]}" + ;; + p|port) + port="${kv[1]}" + ;; + u|user) + xuser+=("${kv[1]}") + ;; + x|xconf) + xconf="${kv[1]}" + ;; + xtls) + flow="xtls-rprx-vision" + ;; + esac +done + +if [ -z "${certhome}" ]; then + echo "Error: certhome undefined." + usage + exit 1 +fi + +if [ -z "${domain}" ]; then + echo "Error: domain undefined." + usage + exit 1 +fi + +if [ -n "${flow}" ]; then + flowopt="-f ${flow}" +fi + +if [ -z "${port}" ]; then + echo "Error: port undefined." + usage + exit 1 ; +fi + +if [ -z "${xuser}" ]; then + echo "Error: user undefined." + usage + exit 1 +fi + +if [ -z "${xconf}" ]; then + echo "Error: xconf undefined." + usage + exit 1 +fi + +if [ -f "${certhome}/${domain}/fullchain.cer" ] && [ -f "${certhome}/${domain}/${domain}.key" ]; then + fullchain="${certhome}/${domain}/fullchain.cer" + prvkey="${certhome}/${domain}/${domain}.key" +fi + +if [ ! -f "${fullchain}" ] || [ ! -f "${prvkey}" ]; then + echo "TLS cert missing?" + echo "Abort." + exit 2 +fi + +if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi + +XCONF=$xconf +# Remove existing port number if existing. +cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $XCONF + +# Add inbound element +cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"vmess", "settings":{"clients":[]}}]' |sponge $XCONF +cat $XCONF |jq --arg port "${port}" '( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' |sponge $XCONF + +# User settings +for xu in "${xuser[@]}" +do + cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c mtt.$dest $flowopt | sponge $XCONF +done + +# Fallback settings +for fb in "${fallback[@]}" +do + cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF +done + +# Network settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"tcp"} ' \ +|sponge $XCONF + +# TLS settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"tls"} ' \ +|sponge $XCONF + +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{}} ' \ +|sponge $XCONF + +cat $XCONF |jq --arg port "${port}" --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings.tlsSettings ) += {"certificates":[{"certificateFile":$fullchain, "keyFile":$prvkey}]} ' \ +|sponge $XCONF diff --git a/server-mwp.sh b/server-mwp.sh new file mode 100755 index 0000000..45cfde8 --- /dev/null +++ b/server-mwp.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +DIR=`dirname $0` + +usage() { + echo "VMESS-WS-PLAIN builder" + echo "Usage: server-mwp ,,,,..." +} + +options=(`echo $1 |tr ',' ' '`) +for option in "${options[@]}" +do + kv=(`echo $option |tr '=' ' '`) + case "${kv[0]}" in + p|port) + port="${kv[1]}" + ;; + u|user) + xuser+=("${kv[1]}") + ;; + w|wpath) + webpath="${kv[1]}" + ;; + x|xconf) + xconf="${kv[1]}" + ;; + esac +done + +if [ -z "${port}" ]; then + echo "Error: port undefined." + usage + exit 1 ; +fi + +if [ -z "${wspath}" ]; then + echo "Error: wspath undefined." + usage + exit 1 +fi + +if [ -z "${xuser}" ]; then + echo "Error: user undefined." + usage + exit 1 +fi + +if [ -z "${xconf}" ]; then + echo "Error: xconf 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 +# Remove existing port number if existing. +cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $XCONF + +# Add inbound element +cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"vmess", "settings":{"clients":[]}}]' |sponge $XCONF +cat $XCONF |jq --arg port "${port}" '( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' |sponge $XCONF + +# User settings +for xu in "${xuser[@]}" +do + cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c mwp.$domain $flowopt | sponge $XCONF +done + +# Network settings +cat $XCONF |jq --arg port "${port}" --arg wspath "${wspath}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"ws","wsSettings":{"path":$wspath}}' \ +|sponge $XCONF + +# Plain settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"none" } ' \ +|sponge $XCONF diff --git a/server-msw.sh b/server-mwt.sh similarity index 50% rename from server-msw.sh rename to server-mwt.sh index e479340..262d326 100755 --- a/server-msw.sh +++ b/server-mwt.sh @@ -1,7 +1,10 @@ #!/bin/bash +DIR=`dirname $0` + usage() { - echo "Usage: server-msw ,,,,," + echo "VMESS-WS-TLS builder" + echo "Usage: server-mwt ,,,,,,..." } options=(`echo $1 |tr ',' ' '`) @@ -9,26 +12,32 @@ for option in "${options[@]}" do kv=(`echo $option |tr '=' ' '`) case "${kv[0]}" in - x|xconf) - xconf="${kv[1]}" - ;; c|certhome) certhome="${kv[1]}" ;; - p|port) - port="${kv[1]}" - ;; d|domain) domain="${kv[1]}" ;; + f|fallback) + fallback+=("${kv[1]}") + ;; + flow) + flow="${kv[1]}" + ;; + p|port) + port="${kv[1]}" + ;; u|user) xuser+=("${kv[1]}") ;; w|wpath) wspath="${kv[1]}" ;; - f|fallback) - fallback+=("${kv[1]}") + x|xconf) + xconf="${kv[1]}" + ;; + xtls) + flow="xtls-rprx-vision" ;; esac done @@ -39,18 +48,24 @@ if [ -z "${certhome}" ]; then exit 1 fi -if [ -z "${xconf}" ]; then - echo "Error: xconf undefined." +if [ -z "${domain}" ]; then + echo "Error: domain undefined." usage exit 1 fi -if [ -z "${port}" ]; then - port=443 +if [ -n "${flow}" ]; then + flowopt="-f ${flow}" fi -if [ -z "${domain}" ]; then - echo "Error: domain undefined." +if [ -z "${port}" ]; then + echo "Error: port undefined." + usage + exit 1 ; +fi + +if [ -z "${wspath}" ]; then + echo "Error: wspath undefined." usage exit 1 fi @@ -61,97 +76,12 @@ if [ -z "${xuser}" ]; then exit 1 fi -if [ -z "${wspath}" ]; then - echo "Error: wspath undefined." +if [ -z "${xconf}" ]; then + echo "Error: xconf 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 -# Remove existing port number if existing. -cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $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=[:level:email]" - echo "Like: user=myid:0:me@g.cn" - echo "Like: user=myid::me@g.cn" - echo "Like: user=myid:0" - echo "Like: user=myid" - exit 1 - fi - if [ -z "${uopt[1]}" ]; then - uopt[1]=0 - 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":"tls" } ' \ -|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 - if [ -f "${certhome}/${domain}/fullchain.cer" ] && [ -f "${certhome}/${domain}/${domain}.key" ]; then fullchain="${certhome}/${domain}/fullchain.cer" prvkey="${certhome}/${domain}/${domain}.key" @@ -163,6 +93,42 @@ if [ ! -f "${fullchain}" ] || [ ! -f "${prvkey}" ]; then exit 2 fi +if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi + +XCONF=$xconf +# Remove existing port number if existing. +cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $XCONF + +# Add inbound element +cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"vmess", "settings":{"clients":[]}}]' |sponge $XCONF +cat $XCONF |jq --arg port "${port}" '( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' |sponge $XCONF + +# User settings +for xu in "${xuser[@]}" +do + cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c mwt.$domain $flowopt | sponge $XCONF +done + +# Fallback settings +for fb in "${fallback[@]}" +do + cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF +done + +# Network settings +cat $XCONF |jq --arg port "${port}" --arg wspath "${wspath}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"ws","wsSettings":{"path":$wspath}} ' \ +|sponge $XCONF + +# TLS settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"tls"} ' \ +|sponge $XCONF + +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{}} ' \ +|sponge $XCONF + cat $XCONF |jq --arg port "${port}" --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ '( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings.tlsSettings ) += {"certificates":[{"certificateFile":$fullchain, "keyFile":$prvkey}]} ' \ |sponge $XCONF diff --git a/server-tpw.sh b/server-tpw.sh deleted file mode 100755 index eeced06..0000000 --- a/server-tpw.sh +++ /dev/null @@ -1,129 +0,0 @@ -#!/bin/bash - -usage() { - echo "Usage: server-tpw ,," -} - -port=443 - -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 "${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 -# Remove existing port number if existing. -cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $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 - 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}" --arg wspath "${wspath}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"wsSettings":{"path":$wspath}} ' \ -|sponge $XCONF diff --git a/server-ts.sh b/server-ts.sh deleted file mode 100755 index 47ae46b..0000000 --- a/server-ts.sh +++ /dev/null @@ -1,155 +0,0 @@ -#!/bin/bash - -usage() { - echo "Usage: server-ts ,,,," -} - -options=(`echo $1 |tr ',' ' '`) -for option in "${options[@]}" -do - kv=(`echo $option |tr '=' ' '`) - case "${kv[0]}" in - x|xconf) - xconf="${kv[1]}" - ;; - c|certhome) - certhome="${kv[1]}" - ;; - p|port) - port="${kv[1]}" - ;; - d|domain) - domain="${kv[1]}" - ;; - u|user) - xuser+=("${kv[1]}") - ;; - f|fallback) - fallback+=("${kv[1]}") - ;; - esac -done - -if [ -z "${certhome}" ]; then - echo "Error: certhome undefined." - usage - exit 1 -fi - -if [ -z "${xconf}" ]; then - echo "Error: xconf 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 [ -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 -# Remove existing port number if existing. -cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $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 - 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":"tcp", "security":"tls" } ' \ -|sponge $XCONF - -cat $XCONF |jq --arg port "${port}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{"alpn":["http/1.1"]} } ' \ -|sponge $XCONF - -if [ -f "${certhome}/${domain}/fullchain.cer" ] && [ -f "${certhome}/${domain}/${domain}.key" ]; then - fullchain="${certhome}/${domain}/fullchain.cer" - prvkey="${certhome}/${domain}/${domain}.key" -fi - -if [ ! -f "${fullchain}" ] || [ ! -f "${prvkey}" ]; then - echo "TLS cert missing?" - echo "Abort." - exit 2 -fi - -cat $XCONF |jq --arg port "${port}" --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings.tlsSettings ) += {"certificates":[{"certificateFile":$fullchain, "keyFile":$prvkey}]} ' \ -|sponge $XCONF diff --git a/server-ttt.sh b/server-ttt.sh new file mode 100755 index 0000000..91b5b61 --- /dev/null +++ b/server-ttt.sh @@ -0,0 +1,126 @@ +#!/bin/bash + +DIR=`dirname $0` + +usage() { + echo "TROJAN-TCP-TLS builder" + echo "Usage: server-ttt ,,,,,..." +} + +options=(`echo $1 |tr ',' ' '`) +for option in "${options[@]}" +do + kv=(`echo $option |tr '=' ' '`) + case "${kv[0]}" in + case "${kv[0]}" in + c|certhome) + certhome="${kv[1]}" + ;; + d|domain) + domain="${kv[1]}" + ;; + f|fallback) + fallback+=("${kv[1]}") + ;; + flow) + flow="${kv[1]}" + ;; + p|port) + port="${kv[1]}" + ;; + u|user) + xuser+=("${kv[1]}") + ;; + x|xconf) + xconf="${kv[1]}" + ;; + xtls) + flow="xtls-rprx-vision" + ;; + esac +done + +if [ -z "${certhome}" ]; then + echo "Error: certhome undefined." + usage + exit 1 +fi + +if [ -z "${domain}" ]; then + echo "Error: domain undefined." + usage + exit 1 +fi + +if [ -n "${flow}" ]; then + flowopt="-f ${flow}" +fi + +if [ -z "${port}" ]; then + echo "Error: port undefined." + usage + exit 1 ; +fi + +if [ -z "${xuser}" ]; then + echo "Error: user undefined." + usage + exit 1 +fi + +if [ -z "${xconf}" ]; then + echo "Error: xconf undefined." + usage + exit 1 +fi + +if [ -f "${certhome}/${domain}/fullchain.cer" ] && [ -f "${certhome}/${domain}/${domain}.key" ]; then + fullchain="${certhome}/${domain}/fullchain.cer" + prvkey="${certhome}/${domain}/${domain}.key" +fi + +if [ ! -f "${fullchain}" ] || [ ! -f "${prvkey}" ]; then + echo "TLS cert missing?" + echo "Abort." + exit 2 +fi + +if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi + +XCONF=$xconf +# Remove existing port number if existing. +cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $XCONF + +# Add inbound element +cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"trojan", "settings":{"clients":[]}}]' |sponge $XCONF +cat $XCONF |jq --arg port "${port}" '( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' |sponge $XCONF + +# User settings +for xu in "${xuser[@]}" +do + cat $XCONF | ${DIR}/addusertj.sh -p $port -u ${xu} -c ttt.$dest $flowopt | sponge $XCONF +done + +# Fallback settings +for fb in "${fallback[@]}" +do + cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF +done + +# Network settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"tcp"} ' \ +|sponge $XCONF + +# TLS settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"tls"} ' \ +|sponge $XCONF + +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{}} ' \ +|sponge $XCONF + +cat $XCONF |jq --arg port "${port}" --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings.tlsSettings ) += {"certificates":[{"certificateFile":$fullchain, "keyFile":$prvkey}]} ' \ +|sponge $XCONF diff --git a/server-twp.sh b/server-twp.sh new file mode 100755 index 0000000..2b75e02 --- /dev/null +++ b/server-twp.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +DIR=`dirname $0` + +usage() { + echo "TROJAN-WS-PLAIN builder" + echo "Usage: server-twp ,,,,..." +} + +options=(`echo $1 |tr ',' ' '`) +for option in "${options[@]}" +do + kv=(`echo $option |tr '=' ' '`) + case "${kv[0]}" in + p|port) + port="${kv[1]}" + ;; + u|user) + xuser+=("${kv[1]}") + ;; + w|wpath) + wspath="${kv[1]}" + ;; + x|xconf) + xconf="${kv[1]}" + ;; + esac +done + +if [ -z "${port}" ]; then + echo "Error: port undefined." + usage + exit 1 ; +fi + +if [ -z "${wspath}" ]; then + echo "Error: wspath undefined." + usage + exit 1 +fi + +if [ -z "${xuser}" ]; then + echo "Error: user undefined." + usage + exit 1 +fi + +if [ -z "${xconf}" ]; then + echo "Error: xconf 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 +# Remove existing port number if existing. +cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $XCONF + +# Add inbound element +cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"trojan", "settings":{"clients":[]}}]' |sponge $XCONF +cat $XCONF |jq --arg port "${port}" '( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' |sponge $XCONF + +# User settings +for xu in "${xuser[@]}" +do + cat $XCONF | ${DIR}/addusertj.sh -p $port -u ${xu} -c twp.$domain $flowopt | sponge $XCONF +done + +# Network settings +cat $XCONF |jq --arg port "${port}" --arg wspath "${wspath}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"ws","wsSettings":{"path":$wspath}} ' \ +|sponge $XCONF + +# Plain settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"none" } ' \ +|sponge $XCONF diff --git a/server-tsw.sh b/server-twt.sh similarity index 50% rename from server-tsw.sh rename to server-twt.sh index ca5d4f5..a6190da 100755 --- a/server-tsw.sh +++ b/server-twt.sh @@ -1,7 +1,10 @@ #!/bin/bash +DIR=`dirname $0` + usage() { - echo "Usage: server-tsw ,,,," + echo "TROJAN-WS-TLS builder" + echo "Usage: server-twt ,,,,,,..." } options=(`echo $1 |tr ',' ' '`) @@ -9,26 +12,32 @@ for option in "${options[@]}" do kv=(`echo $option |tr '=' ' '`) case "${kv[0]}" in - x|xconf) - xconf="${kv[1]}" - ;; c|certhome) certhome="${kv[1]}" ;; - p|port) - port="${kv[1]}" - ;; d|domain) domain="${kv[1]}" ;; + f|fallback) + fallback+=("${kv[1]}") + ;; + flow) + flow="${kv[1]}" + ;; + p|port) + port="${kv[1]}" + ;; u|user) xuser+=("${kv[1]}") ;; w|wpath) wspath="${kv[1]}" ;; - f|fallback) - fallback+=("${kv[1]}") + x|xconf) + xconf="${kv[1]}" + ;; + xtls) + flow="xtls-rprx-vision" ;; esac done @@ -39,18 +48,24 @@ if [ -z "${certhome}" ]; then exit 1 fi -if [ -z "${xconf}" ]; then - echo "Error: xconf undefined." +if [ -z "${domain}" ]; then + echo "Error: domain undefined." usage exit 1 fi -if [ -z "${port}" ]; then - port=443 +if [ -n "${flow}" ]; then + flowopt="-f ${flow}" fi -if [ -z "${domain}" ]; then - echo "Error: domain undefined." +if [ -z "${port}" ]; then + echo "Error: port undefined." + usage + exit 1 ; +fi + +if [ -z "${wspath}" ]; then + echo "Error: wspath undefined." usage exit 1 fi @@ -61,97 +76,12 @@ if [ -z "${xuser}" ]; then exit 1 fi -if [ -z "${wspath}" ]; then - echo "Error: wspath undefined." +if [ -z "${xconf}" ]; then + echo "Error: xconf 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 -# Remove existing port number if existing. -cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $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 - 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":"tls" } ' \ -|sponge $XCONF - -cat $XCONF |jq --arg port "${port}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{"alpn":["h2,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 - if [ -f "${certhome}/${domain}/fullchain.cer" ] && [ -f "${certhome}/${domain}/${domain}.key" ]; then fullchain="${certhome}/${domain}/fullchain.cer" prvkey="${certhome}/${domain}/${domain}.key" @@ -163,6 +93,42 @@ if [ ! -f "${fullchain}" ] || [ ! -f "${prvkey}" ]; then exit 2 fi +if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi + +XCONF=$xconf +# Remove existing port number if existing. +cat $XCONF |jq --arg port "${port}" 'del( .inbounds[] | select(.port == ($port|tonumber)) )' |sponge $XCONF + +# Add inbound element +cat $XCONF |jq --arg port "${port}" '.inbounds +=[{"port":($port|tonumber), "protocol":"trojan", "settings":{"clients":[]}}]' |sponge $XCONF +cat $XCONF |jq --arg port "${port}" '( .inbounds[] | select(.port == ($port|tonumber)) | .settings.decryption ) += "none" ' |sponge $XCONF + +# User settings +for xu in "${xuser[@]}" +do + cat $XCONF | ${DIR}/addusertj.sh -p $port -u ${xu} -c twt.$domain $flowopt | sponge $XCONF +done + +# Fallback settings +for fb in "${fallback[@]}" +do + cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF +done + +# Network settings +cat $XCONF |jq --arg port "${port}" --arg wspath "${wspath}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"ws","wsSettings":{"path":$wspath}} ' \ +|sponge $XCONF + +# TLS settings +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"tls"} ' \ +|sponge $XCONF + +cat $XCONF |jq --arg port "${port}" \ +'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{}} ' \ +|sponge $XCONF + cat $XCONF |jq --arg port "${port}" --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ '( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings.tlsSettings ) += {"certificates":[{"certificateFile":$fullchain, "keyFile":$prvkey}]} ' \ |sponge $XCONF