From 5562f3c0ce4e8e43d67262ad1599477dddff444d Mon Sep 17 00:00:00 2001 From: Samuel Huang Date: Tue, 24 Sep 2024 11:32:50 +1000 Subject: [PATCH] Rewrite with json stdout --- Dockerfile | 3 - run.sh | 85 ++++++++++++---------------- server-lgp.sh | 104 +++++++++++++++++++++-------------- server-lgr.sh | 143 +++++++++++++++++++++++++----------------------- server-lgt.sh | 130 ++++++++++++++++++++----------------------- server-lsp.sh | 96 +++++++++++++++++++------------- server-lst.sh | 124 +++++++++++++++++++---------------------- server-ltr.sh | 124 +++++++++++++++++++++-------------------- server-ltt.sh | 117 ++++++++++++++++----------------------- server-lwp.sh | 96 +++++++++++++++++++------------- server-lwt.sh | 124 +++++++++++++++++++---------------------- server-mtt.sh | 119 ++++++++++++++++++---------------------- server-mwp.sh | 99 ++++++++++++++++++++------------- server-mwt.sh | 127 ++++++++++++++++++++---------------------- server-nginx.sh | 8 +-- server-ttt.sh | 119 ++++++++++++++++++---------------------- server-twp.sh | 109 +++++++++++++++++++++++++++++++++++- server-twt.sh | 125 ++++++++++++++++++++---------------------- 18 files changed, 965 insertions(+), 887 deletions(-) diff --git a/Dockerfile b/Dockerfile index fdca7e3..4dde687 100644 --- a/Dockerfile +++ b/Dockerfile @@ -56,9 +56,6 @@ ADD server-ttt.sh /server-ttt.sh ADD server-twt.sh /server-twt.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 diff --git a/run.sh b/run.sh index 71db486..87917e5 100755 --- a/run.sh +++ b/run.sh @@ -2,7 +2,7 @@ DIR=`dirname $0` DIR="$(cd $DIR; pwd)" -CERTHOME="/root/.acme.sh" +CERTHOME="/opt/cert" XCONF=/tmp/server-xray.json usage() { @@ -36,7 +36,7 @@ usage() { 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 " -j|--json Json snippet to merge into the config. Say '{"log":{"loglevel":"info"}}'" echo " -d|--debug Start in debug mode with verbose output" } @@ -61,7 +61,8 @@ while true ; do shift 2 ;; -i|--stdin) - STDINCONF=1 + # Read Xray config from STDIN. Run Xray only. + exec /usr/local/bin/xray shift 1 ;; -d|--debug) @@ -77,33 +78,34 @@ while true ; do shift 2 ;; --lgp|--lgr|--lgt|--lsp|--lst|--ltr|--ltt|--lwp|--lwt|--mtt|--mwp|--mwt|--ttt|--twp|--twt) + # Alias options SVC=`echo $1|tr -d '\-\-'` SVCMD+=("${DIR}/server-${SVC}.sh $2") shift 2 ;; - # Alias options --ltrx|--lttx) + # Alias options SVC=`echo $1|tr -d '\-\-'|tr -d x` SVCMD+=("${DIR}/server-${SVC}.sh $2,xtls") shift 2 ;; --domain-block) Jrules=`echo "${Jrules}" | jq --arg blkdomain "$2" \ - '.rules += [{"type":"field", "outboundTag":"blocked", "domain":[$blkdomain]}]'` + '.rules += [{"type":"field","outboundTag":"blocked","domain":[$blkdomain]}]'` shift 2 ;; --ip-block) Jrules=`echo "${Jrules}" | jq --arg blkip "$2" \ - '.rules += [{"type":"field", "outboundTag":"blocked", "ip":[$blkip]}]'` + '.rules += [{"type":"field","outboundTag":"blocked","ip":[$blkip]}]'` shift 2 ;; --cn-block) Jrules=`echo "${Jrules}" | jq --arg igndomain "geosite:geolocation-cn" \ - '.rules += [{"type":"field", "outboundTag":"blocked", "domain":[$igndomain]}]'` + '.rules += [{"type":"field","outboundTag":"blocked","domain":[$igndomain]}]'` Jrules=`echo "${Jrules}" | jq --arg igndomain "geosite:cn" \ - '.rules += [{"type":"field", "outboundTag":"blocked", "domain":[$igndomain]}]'` + '.rules += [{"type":"field","outboundTag":"blocked","domain":[$igndomain]}]'` Jrules=`echo "${Jrules}" | jq --arg ignip "geoip:cn" \ - '.rules += [{"type":"field", "outboundTag":"blocked", "ip":[$ignip]}]'` + '.rules += [{"type":"field","outboundTag":"blocked","ip":[$ignip]}]'` shift 1 ;; --ng-server) @@ -165,29 +167,12 @@ if [ -n "${CERTDOMAIN}" ]; then done fi -echo '{"log":{"loglevel":"warning"},"inbounds":[],"outbounds":[{"tag":"direct","protocol":"freedom"},{"tag":"blocked","protocol":"blackhole"}]}' |jq .|sponge $XCONF - -xopt="xconf=$XCONF" -xopt="$xopt,certhome=$CERTHOME" -for uopt in "${UOPT[@]}" -do - xopt="$xopt,$uopt" -done - -# Add routing config -Jrouting='{"routing": {"domainStrategy":"AsIs"}}' -Jrouting=`echo "${Jrouting}" |jq --argjson jrules "${Jrules}" '.routing += $jrules'` -cat $XCONF| jq --argjson jrouting "${Jrouting}" '. += $jrouting' | sponge $XCONF - -# Run Xray only. Read Xray config from STDIN -if [ "${STDINCONF}" = "1" ]; then - exec /usr/local/bin/xray -fi +xopt="certhome=$CERTHOME" +for uopt in "${UOPT[@]}"; do xopt="$xopt,$uopt"; done if [ -z "${SVCMD}" ]; then - echo "No Xray service creation found. Quit." - usage; - exit 1 + echo -e "No Xray service creation found. Quit.\n" + usage; exit 1 fi # Start Nginx if necessary @@ -214,46 +199,48 @@ if [ -n "${NGOPT}" ]; then ngcmd="${DIR}/server-nginx.sh $NGOPT" $ngcmd ret=$?; if [ $ret != 0 ]; then - echo "" - echo "Nginx config generation failed from the following cmd:\n$ngcmd"; - echo "Please check log for details" + echo -e "\nNginx config generation failed from the following cmd:\n$ngcmd"; + echo -e "Please check log for details.\n" exit $ret; fi killall nginx nginx; fi +# Add root config +Jroot='{"outbounds":[{"tag":"direct","protocol":"freedom"},{"tag":"blocked","protocol":"blackhole"}]}' + +# Add routing config +Jrouting='{"routing":{"domainStrategy":"AsIs"}}' +Jrouting=`echo $Jrouting |jq --argjson jrules "${Jrules}" '.routing += $jrules'` + +Jroot=`echo $Jroot| jq --argjson jrouting "${Jrouting}" '. += $jrouting'` + # Xray service config generation for svcmd in "${SVCMD[@]}" do - svcmd="$svcmd,$xopt" - $svcmd + Jsvc=`$svcmd,$xopt` if [[ $? -ne 0 ]]; then - echo - echo "Service creation command failed: $svcmd" + echo "Service creation command failed: $svcmd,$xopt" exit 1 fi + Jroot=`echo $Jroot| jq --argjson Jsvc "${Jsvc}" '.inbounds += [$Jsvc]'` done -if [ "${DEBUG}" = "1" ]; then - cat $XCONF |jq '.log.loglevel |="debug"' |sponge $XCONF - echo -fi +if [ -n "${DEBUG}" ]; then loglevel="debug"; else loglevel="warning"; fi +Jroot=`echo $Jroot| jq --arg loglevel "${loglevel}" '.log.loglevel |= $loglevel'` if [ -n "${INJECT}" ]; then for JSON_IN in "${INJECT[@]}" do - echo "${JSON_IN}"|jq -ec >/tmp/merge.json - if [[ $? -ne 0 ]]; then - echo "Invalid json ${JSON_IN}" - exit 1 - fi - jq -s '.[0] * .[1]' $XCONF /tmp/merge.json |sponge $XCONF + Jmerge=`jq -nc "${JSON_IN}"` + if [[ $? -ne 0 ]]; then echo "Invalid json ${JSON_IN}"; exit 1; fi + Jroot=`jq -n --argjson Jroot "${Jroot}" --argjson Jmerge "${Jmerge}" '$Jroot + $Jmerge'` done fi -cat $XCONF -echo +jq -n "$Jroot" +jq -n "$Jroot">$XCONF exec /usr/local/bin/xray -c $XCONF fi diff --git a/server-lgp.sh b/server-lgp.sh index fc40c0e..4a735f4 100755 --- a/server-lgp.sh +++ b/server-lgp.sh @@ -3,8 +3,10 @@ DIR=`dirname $0` usage() { - echo "VLESS-GRPC-PLAIN server builder" - echo "Usage: server-lgp ,,,,..." + >&2 echo "VLESS-GRPC-PLAIN server builder" + >&2 echo "Usage: server-lgp ,,,,...,[proxy_acpt],[fallback=host:port:path]" + >&2 echo "Fallback format: fallback=[host]<:port>[:/path] Like: 'baidu.com:443:/path', ':1443:/path', ':1443'" + >&2 echo "User format: user|u=[:level:email]" } options=(`echo $1 |tr ',' ' '`) @@ -15,67 +17,85 @@ do d|domain) domain="${kv[1]}" ;; + f|fallback) + fallback+=("${kv[1]}") + ;; p|port) port="${kv[1]}" ;; - s|service) - service="${kv[1]}" + proxy_acpt) + acceptProxyProtocol=true + ;; + s|serviceName) + serviceName="${kv[1]}" ;; u|user) xuser+=("${kv[1]}") ;; - x|xconf) - xconf="${kv[1]}" - ;; esac done -if [ -z "${port}" ]; then - echo "Error: port undefined." - usage - exit 1 ; +if [ -z "${domain}" ]; then + >&2 echo -e "Error: Domain undefined.\n" + usage; exit 1 fi -if [ -z "${service}" ]; then - echo "Error: service undefined." - usage - exit 1 +if [ -z "${port}" ]; then + >&2 echo -e "Error: Port undefined.\n" + usage; exit 1 ; +fi + +if [ -z "${serviceName}" ]; then + >&2 echo -e "Error: serviceName undefined.\n" + usage; exit 1 fi if [ -z "${xuser}" ]; then - echo "Error: user undefined." - usage - exit 1 + >&2 echo -e "Error: User undefined.\n" + 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 -e "Error: Port number must be numeric.\n"; 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 +# inbound frame +inbound=`jq -nc --arg port "${port}" '{"port":$port,"protocol":"vless","settings":{"decryption":"none"}}'` # User settings -for xu in "${xuser[@]}" +for user in "${xuser[@]}" do - cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c lgp.$domain $flowopt | sponge $XCONF + IFS=':'; uopt=(${user}); uopt=(${uopt[@]}) + uid="${uopt[0]}"; level="${uopt[1]}"; email="${uopt[2]}" + unset IFS + if [ -z "${uid}" ]; then >&2 echo "Incorrect user format: $user"; usage; exit 1; fi + if [ -z "${level}" ]; then level=0; fi + if [ -z "${email}" ]; then email="${uid}@lgp.$domain"; fi + inbound=`echo $inbound| jq -c --arg uid "${uid}" --arg flow "${flow}" --arg level "${level}" --arg email "${email}" \ + '.settings.clients += [{"id":$uid,"level":($level|tonumber),"email":$email,"flow":$flow}]'` 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 +# StreamSettings +if [ -n "${acceptProxyProtocol}" ]; then + inbound=`echo $inbound| jq -c '.settings.streamSettings.sockopt += {"acceptProxyProtocol":true}'` +fi -# Plain settings -cat $XCONF |jq --arg port "${port}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"none" } ' \ -|sponge $XCONF +# Network settings +inbound=`echo $inbound| jq -c --arg serviceName "${serviceName}" '.settings.streamSettings += {"network":"grpc","grpcSettings":{"serviceName":$serviceName}}'` + +# Security settings +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"security":"none"}'` + +# Fallback settings +for fb in "${fallback[@]}" +do + IFS=':'; fopt=(${fb}); fopt=(${fopt[@]}) + fhost="${fopt[0]}"; fport="${fopt[1]}"; fpath="${fopt[2]}" + unset IFS + if [ -z "${fport}" ]; then >&2 echo "Incorrect fallback format: ${fallback}"; usage; exit 1; fi + if [ -z "${fhost}" ]; then fhost="127.0.0.1"; fi + fdest="$fhost:$fport" + Jfb=`jq -nc --arg fdest "${fdest}" --arg fpath "${fpath}" '. |= {"dest":$fdest,"path":$fpath,"xver":1}'` + inbound=`echo $inbound| jq -c --argjson Jfb "${Jfb}" '.settings.fallbacks += [$Jfb]'` +done + +echo $inbound +exit 0 diff --git a/server-lgr.sh b/server-lgr.sh index 453fac9..9d3ad26 100755 --- a/server-lgr.sh +++ b/server-lgr.sh @@ -3,8 +3,10 @@ DIR=`dirname $0` usage() { - echo "VLESS-GRPC-REALITY server builder" - echo "Usage: server-lgr ,,,,[xtls],,[pub=xx,prv=yy,shortId=zz],,..." + >&2 echo "VLESS-GRPC-REALITY server builder" + >&2 echo "Usage: server-lgr ,,,,[pub=xx],[shortId=zz],,,...,[proxy_acpt],[fallback=host:port:path],[xtls]" + >&2 echo "Fallback format: fallback=[host]<:port>[:/path] Like: 'baidu.com:443:/path', ':1443:/path', ':1443'" + >&2 echo "User format: user|u=[:level:email]" } options=(`echo $1 |tr ',' ' '`) @@ -12,9 +14,6 @@ for option in "${options[@]}" do kv=(`echo $option |tr '=' ' '`) case "${kv[0]}" in - c|certhome) - certhome="${kv[1]}" - ;; d|dest) dest="${kv[1]}" ;; @@ -27,10 +26,16 @@ do p|port) port="${kv[1]}" ;; - s|service) - service="${kv[1]}" + proxy_acpt) + acceptProxyProtocol=true ;; - shortId) + svnm|serverName) + serverNames+=("${kv[1]}") + ;; + s|serviceName) + serviceName="${kv[1]}" + ;; + sid|shortId) shortIds+=("${kv[1]}") ;; prv|privateKey) @@ -42,9 +47,6 @@ do u|user) xuser+=("${kv[1]}") ;; - x|xconf) - xconf="${kv[1]}" - ;; xtls) flow="xtls-rprx-vision" ;; @@ -52,83 +54,88 @@ do done if [ -z "${dest}" ]; then - echo "Error: dest undefined." - usage - exit 1 -fi - -if [ -n "${flow}" ]; then - flowopt="-f ${flow}" + >&2 echo -e "Error: Fake Destination undefined.\n" + usage; exit 1 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 + >&2 echo -e "Error: Port undefined.\n" + usage; exit 1 ; fi if [ -z "${prvkey}" ]; then - echo "Warning: PrivateKey undefined, Generated new..." + >&2 echo "Warning: PrivateKey undefined, Generated new..." kv=(`/usr/local/bin/xray x25519|cut -d ' ' -f3|tr ' '`) prvkey="${kv[0]}" pubkey="${kv[1]}" - echo "PublicKey: $pubkey" + >&2 echo "PublicKey: $pubkey" fi -if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi +if [ -z "${serviceName}" ]; then + >&2 echo -e "Error: serviceName undefined.\n" + usage; 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 +if [ -z "${xuser}" ]; then + >&2 echo -e "Error: User undefined.\n" + usage; exit 1 +fi -# 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 +if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo -e "Error: Port number must be numeric.\n"; exit 1; fi + +# inbound frame +inbound=`jq -nc --arg port "${port}" '{"port":$port,"protocol":"vless","settings":{"decryption":"none"}}'` # User settings -for xu in "${xuser[@]}" +for user in "${xuser[@]}" do - cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c lgr.$dest $flowopt | sponge $XCONF + IFS=':'; uopt=(${user}); uopt=(${uopt[@]}) + uid="${uopt[0]}"; level="${uopt[1]}"; email="${uopt[2]}" + unset IFS + if [ -z "${uid}" ]; then >&2 echo "Incorrect user format: $user"; usage; exit 1; fi + if [ -z "${level}" ]; then level=0; fi + if [ -z "${email}" ]; then email="${uid}@lgr.$dest"; fi + inbound=`echo $inbound| jq -c --arg uid "${uid}" --arg flow "${flow}" --arg level "${level}" --arg email "${email}" \ + '.settings.clients += [{"id":$uid,"level":($level|tonumber),"email":$email,"flow":$flow}]'` done +# StreamSettings +if [ -n "${acceptProxyProtocol}" ]; then + inbound=`echo $inbound| jq -c '.settings.streamSettings.sockopt += {"acceptProxyProtocol":true}'` +fi + +# Network settings +inbound=`echo $inbound| jq -c --arg serviceName "${serviceName}" '.settings.streamSettings += {"network":"grpc","grpcSettings":{"serviceName":$serviceName}}'` + +# Security settings +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"security":"reality"}'` + +# Reality settings +inbound=`echo $inbound| jq -c --arg dest "${dest}" --arg pubkey "${pubkey}" --arg prvkey "${prvkey}" \ +'.settings.streamSettings.realitySettings += {"show":true,"dest":"\($dest):443","serverNames":[$dest],"privateKey":$prvkey,"publicKey":$pubkey}'` + +# serverNames settings +if [ -n "${serverNames}" ]; then + JserverNames=`printf '%s\n' "${serverNames[@]}"|jq -R|jq -sc` + inbound=`echo $inbound| jq -c --argjson JserverNames "${JserverNames}" '.settings.streamSettings.realitySettings.serverNames += $JserverNames'` +fi + +# shortIds settings +JshortIds=`printf '%s\n' "${shortIds[@]}"|jq -R|jq -sc` +inbound=`echo $inbound| jq -c --argjson JshortIds "${JshortIds}" '.settings.streamSettings.realitySettings.shortIds += $JshortIds'` + # Fallback settings for fb in "${fallback[@]}" do - cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF + IFS=':'; fopt=(${fb}); fopt=(${fopt[@]}) + fhost="${fopt[0]}"; fport="${fopt[1]}"; fpath="${fopt[2]}" + unset IFS + if [ -z "${fport}" ]; then >&2 echo "Incorrect fallback format: ${fallback}"; usage; exit 1; fi + if [ -z "${fhost}" ]; then fhost="127.0.0.1"; fi + fdest="$fhost:$fport" + Jfb=`jq -nc --arg fdest "${fdest}" --arg fpath "${fpath}" '. |= {"dest":$fdest,"path":$fpath,"xver":1}'` + inbound=`echo $inbound| jq -c --argjson Jfb "${Jfb}" '.settings.fallbacks += [$Jfb]'` 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 +echo $inbound +exit 0 diff --git a/server-lgt.sh b/server-lgt.sh index a56259a..46c93f8 100755 --- a/server-lgt.sh +++ b/server-lgt.sh @@ -3,8 +3,10 @@ DIR=`dirname $0` usage() { - echo "VLESS-GRPC-TLS server builder" - echo "Usage: server-lgt ,,,,[xtls],,,..." + >&2 echo "VLESS-GRPC-TLS server builder" + >&2 echo "Usage: server-lgt ,,,,,...,[proxy_acpt],[fallback=host:port:path],[xtls]" + >&2 echo "Fallback format: fallback=[host]<:port>[:/path] Like: 'baidu.com:443:/path', ':1443:/path', ':1443'" + >&2 echo "User format: user|u=[:level:email]" } options=(`echo $1 |tr ',' ' '`) @@ -27,15 +29,15 @@ do p|port) port="${kv[1]}" ;; - s|service) - service="${kv[1]}" + proxy_acpt) + acceptProxyProtocol=true + ;; + s|serviceName) + serviceName="${kv[1]}" ;; u|user) xuser+=("${kv[1]}") ;; - x|xconf) - xconf="${kv[1]}" - ;; xtls) flow="xtls-rprx-vision" ;; @@ -43,92 +45,78 @@ do done if [ -z "${certhome}" ]; then - echo "Error: certhome undefined." - usage - exit 1 + >&2 echo -e "Error: Certhome undefined.\n" + usage; exit 1 fi if [ -z "${domain}" ]; then - echo "Error: domain undefined." - usage - exit 1 -fi - -if [ -n "${flow}" ]; then - flowopt="-f ${flow}" + >&2 echo -e "Error: Domain undefined.\n" + usage; exit 1 fi if [ -z "${port}" ]; then - echo "Error: port undefined." - usage - exit 1 ; + >&2 echo -e "Error: Port undefined.\n" + usage; exit 1 ; fi -if [ -z "${service}" ]; then - echo "Error: service undefined." - usage - exit 1 +if [ -z "${serviceName}" ]; then + >&2 echo -e "Error: serviceName undefined.\n" + usage; exit 1 fi if [ -z "${xuser}" ]; then - echo "Error: user undefined." - usage - exit 1 + >&2 echo -e "Error: User undefined.\n" + usage; exit 1 fi -if [ -z "${xconf}" ]; then - echo "Error: xconf undefined." - usage - exit 1 -fi +fullchain="${certhome}/${domain}/fullchain.cer" +prvkey="${certhome}/${domain}/${domain}.key" +if [ ! -f "${fullchain}" ]; then >&2 echo "Warning, Fullchain not found: ${fullchain}"; fi +if [ ! -f "${prvkey}" ]; then >&2 echo "Warning, Private key not found: ${prvkey}"; 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 ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo -e "Error: Port number must be numeric.\n"; exit 1; 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 +# inbound frame +inbound=`jq -nc --arg port "${port}" '{"port":$port,"protocol":"vless","settings":{"decryption":"none"}}'` # User settings -for xu in "${xuser[@]}" +for user in "${xuser[@]}" do - cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c lgt.$domain $flowopt | sponge $XCONF + IFS=':'; uopt=(${user}); uopt=(${uopt[@]}) + uid="${uopt[0]}"; level="${uopt[1]}"; email="${uopt[2]}" + unset IFS + if [ -z "${uid}" ]; then >&2 echo "Incorrect user format: $user"; usage; exit 1; fi + if [ -z "${level}" ]; then level=0; fi + if [ -z "${email}" ]; then email="${uid}@lgt.$domain"; fi + inbound=`echo $inbound| jq -c --arg uid "${uid}" --arg flow "${flow}" --arg level "${level}" --arg email "${email}" \ + '.settings.clients += [{"id":$uid,"level":($level|tonumber),"email":$email,"flow":$flow}]'` done +# StreamSettings +if [ -n "${acceptProxyProtocol}" ]; then + inbound=`echo $inbound| jq -c '.settings.streamSettings.sockopt += {"acceptProxyProtocol":true}'` +fi + +# Network settings +inbound=`echo $inbound| jq -c --arg serviceName "${serviceName}" '.settings.streamSettings += {"network":"grpc","grpcSettings":{"serviceName":$serviceName}}'` + +# Security settings +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"security":"tls"}'` +inbound=`echo $inbound| jq -c --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ +'.settings.streamSettings.tlsSettings += {"certificates":[{"certificateFile":$fullchain,"keyFile":$prvkey}]}'` + # Fallback settings for fb in "${fallback[@]}" do - cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF + IFS=':'; fopt=(${fb}); fopt=(${fopt[@]}) + fhost="${fopt[0]}"; fport="${fopt[1]}"; fpath="${fopt[2]}" + unset IFS + if [ -z "${fport}" ]; then >&2 echo "Incorrect fallback format: ${fallback}"; usage; exit 1; fi + if [ -z "${fhost}" ]; then fhost="127.0.0.1"; fi + fdest="$fhost:$fport" + Jfb=`jq -nc --arg fdest "${fdest}" --arg fpath "${fpath}" '. |= {"dest":$fdest,"path":$fpath,"xver":1}'` + inbound=`echo $inbound| jq -c --argjson Jfb "${Jfb}" '.settings.fallbacks += [$Jfb]'` 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 +echo $inbound +exit 0 diff --git a/server-lsp.sh b/server-lsp.sh index 43b4722..bef5731 100755 --- a/server-lsp.sh +++ b/server-lsp.sh @@ -3,8 +3,10 @@ DIR=`dirname $0` usage() { - echo "VLESS-SPLT-PLAIN server builder" - echo "Usage: server-lsp ,,,,..." + >&2 echo "VLESS-SPLT-PLAIN server builder" + >&2 echo "Usage: server-lsp ,,,,...,[proxy_acpt],[fallback=host:port:path]" + >&2 echo "Fallback format: fallback=[host]<:port>[:/path] Like: 'baidu.com:443:/path', ':1443:/path', ':1443'" + >&2 echo "User format: user|u=[:level:email]" } options=(`echo $1 |tr ',' ' '`) @@ -15,67 +17,85 @@ do d|domain) domain="${kv[1]}" ;; + f|fallback) + fallback+=("${kv[1]}") + ;; p|port) port="${kv[1]}" ;; + proxy_acpt) + acceptProxyProtocol=true + ;; u|user) xuser+=("${kv[1]}") ;; w|wpath) webpath="${kv[1]}" ;; - x|xconf) - xconf="${kv[1]}" - ;; esac done +if [ -z "${domain}" ]; then + >&2 echo -e "Error: Domain undefined.\n" + usage; exit 1 +fi + if [ -z "${port}" ]; then - echo "Error: port undefined." - usage - exit 1 ; + >&2 echo -e "Error: Port undefined.\n" + usage; exit 1 ; fi if [ -z "${webpath}" ]; then - echo "Error: webpath undefined." - usage - exit 1 + >&2 echo -e "Error: webpath undefined.\n" + usage; exit 1 fi if [ -z "${xuser}" ]; then - echo "Error: user undefined." - usage - exit 1 + >&2 echo -e "Error: User undefined.\n" + 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 -e "Error: Port number must be numeric.\n"; 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 +# inbound frame +inbound=`jq -nc --arg port "${port}" '{"port":$port,"protocol":"vless","settings":{"decryption":"none"}}'` # User settings -for xu in "${xuser[@]}" +for user in "${xuser[@]}" do - cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c lsp.$domain $flowopt | sponge $XCONF + IFS=':'; uopt=(${user}); uopt=(${uopt[@]}) + uid="${uopt[0]}"; level="${uopt[1]}"; email="${uopt[2]}" + unset IFS + if [ -z "${uid}" ]; then >&2 echo "Incorrect user format: $user"; usage; exit 1; fi + if [ -z "${level}" ]; then level=0; fi + if [ -z "${email}" ]; then email="${uid}@lsp.$domain"; fi + inbound=`echo $inbound| jq -c --arg uid "${uid}" --arg flow "${flow}" --arg level "${level}" --arg email "${email}" \ + '.settings.clients += [{"id":$uid,"level":($level|tonumber),"email":$email,"flow":$flow}]'` done -# Network settings -cat $XCONF |jq --arg port "${port}" --arg webpath "${webpath}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"splithttp","splithttpSettings":{"path":$webpath}} ' \ -|sponge $XCONF +# StreamSettings +if [ -n "${acceptProxyProtocol}" ]; then + inbound=`echo $inbound| jq -c '.settings.streamSettings.sockopt += {"acceptProxyProtocol":true}'` +fi -# Plain settings -cat $XCONF |jq --arg port "${port}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"none" } ' \ -|sponge $XCONF +# Network settings +inbound=`echo $inbound| jq -c --arg webpath "${webpath}" '.settings.streamSettings += {"network":"splithttp","splithttpSettings":{"path":$webpath}}'` + +# Security settings +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"security":"none"}'` + +# Fallback settings +for fb in "${fallback[@]}" +do + IFS=':'; fopt=(${fb}); fopt=(${fopt[@]}) + fhost="${fopt[0]}"; fport="${fopt[1]}"; fpath="${fopt[2]}" + unset IFS + if [ -z "${fport}" ]; then >&2 echo "Incorrect fallback format: ${fallback}"; usage; exit 1; fi + if [ -z "${fhost}" ]; then fhost="127.0.0.1"; fi + fdest="$fhost:$fport" + Jfb=`jq -nc --arg fdest "${fdest}" --arg fpath "${fpath}" '. |= {"dest":$fdest,"path":$fpath,"xver":1}'` + inbound=`echo $inbound| jq -c --argjson Jfb "${Jfb}" '.settings.fallbacks += [$Jfb]'` +done + +echo $inbound +exit 0 diff --git a/server-lst.sh b/server-lst.sh index 191d07e..717554b 100755 --- a/server-lst.sh +++ b/server-lst.sh @@ -3,8 +3,10 @@ DIR=`dirname $0` usage() { - echo "VLESS-SPLT-TLS server builder" - echo "Usage: server-lst ,,,,,,..." + >&2 echo "VLESS-SPLT-TLS server builder" + >&2 echo "Usage: server-lst ,,,,,...,[proxy_acpt],[fallback=host:port:path],[xtls]" + >&2 echo "Fallback format: fallback=[host]<:port>[:/path] Like: 'baidu.com:443:/path', ':1443:/path', ':1443'" + >&2 echo "User format: user|u=[:level:email]" } options=(`echo $1 |tr ',' ' '`) @@ -27,15 +29,15 @@ do p|port) port="${kv[1]}" ;; + proxy_acpt) + acceptProxyProtocol=true + ;; u|user) xuser+=("${kv[1]}") ;; w|wpath) webpath="${kv[1]}" ;; - x|xconf) - xconf="${kv[1]}" - ;; xtls) flow="xtls-rprx-vision" ;; @@ -43,92 +45,78 @@ do done if [ -z "${certhome}" ]; then - echo "Error: certhome undefined." - usage - exit 1 + >&2 echo -e "Error: Certhome undefined.\n" + usage; exit 1 fi if [ -z "${domain}" ]; then - echo "Error: domain undefined." - usage - exit 1 -fi - -if [ -n "${flow}" ]; then - flowopt="-f ${flow}" + >&2 echo -e "Error: Domain undefined.\n" + usage; exit 1 fi if [ -z "${port}" ]; then - echo "Error: port undefined." - usage - exit 1 ; + >&2 echo -e "Error: Port undefined.\n" + usage; exit 1 ; fi if [ -z "${webpath}" ]; then - echo "Error: webpath undefined." - usage - exit 1 + >&2 echo -e "Error: webpath undefined.\n" + usage; exit 1 fi if [ -z "${xuser}" ]; then - echo "Error: user undefined." - usage - exit 1 + >&2 echo -e "Error: User undefined.\n" + usage; exit 1 fi -if [ -z "${xconf}" ]; then - echo "Error: xconf undefined." - usage - exit 1 -fi +fullchain="${certhome}/${domain}/fullchain.cer" +prvkey="${certhome}/${domain}/${domain}.key" +if [ ! -f "${fullchain}" ]; then >&2 echo "Warning, Fullchain not found: ${fullchain}"; fi +if [ ! -f "${prvkey}" ]; then >&2 echo "Warning, Private key not found: ${prvkey}"; 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 ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo -e "Error: Port number must be numeric.\n"; exit 1; 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 +# inbound frame +inbound=`jq -nc --arg port "${port}" '{"port":$port,"protocol":"vless","settings":{"decryption":"none"}}'` # User settings -for xu in "${xuser[@]}" +for user in "${xuser[@]}" do - cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c lst.$domain $flowopt | sponge $XCONF + IFS=':'; uopt=(${user}); uopt=(${uopt[@]}) + uid="${uopt[0]}"; level="${uopt[1]}"; email="${uopt[2]}" + unset IFS + if [ -z "${uid}" ]; then >&2 echo "Incorrect user format: $user"; usage; exit 1; fi + if [ -z "${level}" ]; then level=0; fi + if [ -z "${email}" ]; then email="${uid}@lst.$domain"; fi + inbound=`echo $inbound| jq -c --arg uid "${uid}" --arg flow "${flow}" --arg level "${level}" --arg email "${email}" \ + '.settings.clients += [{"id":$uid,"level":($level|tonumber),"email":$email,"flow":$flow}]'` done +# StreamSettings +if [ -n "${acceptProxyProtocol}" ]; then + inbound=`echo $inbound| jq -c '.settings.streamSettings.sockopt += {"acceptProxyProtocol":true}'` +fi + +# Network settings +inbound=`echo $inbound| jq -c --arg webpath "${webpath}" '.settings.streamSettings += {"network":"splithttp","splithttpSettings":{"path":$webpath}}'` + +# Security settings +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"security":"tls"}'` +inbound=`echo $inbound| jq -c --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ +'.settings.streamSettings.tlsSettings += {"certificates":[{"certificateFile":$fullchain,"keyFile":$prvkey}]}'` + # Fallback settings for fb in "${fallback[@]}" do - cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF + IFS=':'; fopt=(${fb}); fopt=(${fopt[@]}) + fhost="${fopt[0]}"; fport="${fopt[1]}"; fpath="${fopt[2]}" + unset IFS + if [ -z "${fport}" ]; then >&2 echo "Incorrect fallback format: ${fallback}"; usage; exit 1; fi + if [ -z "${fhost}" ]; then fhost="127.0.0.1"; fi + fdest="$fhost:$fport" + Jfb=`jq -nc --arg fdest "${fdest}" --arg fpath "${fpath}" '. |= {"dest":$fdest,"path":$fpath,"xver":1}'` + inbound=`echo $inbound| jq -c --argjson Jfb "${Jfb}" '.settings.fallbacks += [$Jfb]'` done -# Network settings -cat $XCONF |jq --arg port "${port}" --arg webpath "${webpath}" \ -'( .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 +echo $inbound +exit 0 diff --git a/server-ltr.sh b/server-ltr.sh index 4a2df6f..2540427 100755 --- a/server-ltr.sh +++ b/server-ltr.sh @@ -3,8 +3,10 @@ DIR=`dirname $0` usage() { - echo "VLESS-TCP-REALITY server builder" - echo "Usage: server-ltr ,,,[xtls],[proxy_acpt],,[pub=xx,prv=yy,shortId=zz],,..." + >&2 echo "VLESS-TCP-REALITY server builder" + >&2 echo "Usage: server-ltr ,,[pub=xx],[shortId=zz],,,...,[proxy_acpt],[fallback=host:port:path],[xtls]" + >&2 echo "Fallback format: fallback=[host]<:port>[:/path] Like: 'baidu.com:443:/path', ':1443:/path', ':1443'" + >&2 echo "User format: user|u=[:level:email]" } options=(`echo $1 |tr ',' ' '`) @@ -12,9 +14,6 @@ for option in "${options[@]}" do kv=(`echo $option |tr '=' ' '`) case "${kv[0]}" in - c|certhome) - certhome="${kv[1]}" - ;; d|dest) dest="${kv[1]}" ;; @@ -30,7 +29,10 @@ do proxy_acpt) acceptProxyProtocol=true ;; - shortId) + svnm|serverName) + serverNames+=("${kv[1]}") + ;; + sid|shortId) shortIds+=("${kv[1]}") ;; prv|privateKey) @@ -42,9 +44,6 @@ do u|user) xuser+=("${kv[1]}") ;; - x|xconf) - xconf="${kv[1]}" - ;; xtls) flow="xtls-rprx-vision" ;; @@ -52,84 +51,83 @@ do done if [ -z "${dest}" ]; then - echo "Error: dest undefined." - usage - exit 1 -fi - -if [ -n "${flow}" ]; then - flowopt="-f ${flow}" + >&2 echo -e "Error: Fake Destination undefined.\n" + usage; exit 1 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 + >&2 echo -e "Error: Port undefined.\n" + usage; exit 1 ; fi if [ -z "${prvkey}" ]; then - echo "Warning: PrivateKey undefined, Generated new..." + >&2 echo "Warning: PrivateKey undefined, Generated new..." kv=(`/usr/local/bin/xray x25519|cut -d ' ' -f3|tr ' '`) prvkey="${kv[0]}" pubkey="${kv[1]}" - echo "PublicKey: $pubkey" + >&2 echo "PublicKey: $pubkey" fi -if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo "Port number must be numeric"; exit 1; fi +if [ -z "${xuser}" ]; then + >&2 echo -e "Error: User undefined.\n" + usage; 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 +if ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo -e "Error: Port number must be numeric.\n"; exit 1; fi -# 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 +# inbound frame +inbound=`jq -nc --arg port "${port}" '{"port":$port,"protocol":"vless","settings":{"decryption":"none"}}'` # User settings -for xu in "${xuser[@]}" +for user 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 + IFS=':'; uopt=(${user}); uopt=(${uopt[@]}) + uid="${uopt[0]}"; level="${uopt[1]}"; email="${uopt[2]}" + unset IFS + if [ -z "${uid}" ]; then >&2 echo "Incorrect user format: $user"; usage; exit 1; fi + if [ -z "${level}" ]; then level=0; fi + if [ -z "${email}" ]; then email="${uid}@ltr.$dest"; fi + inbound=`echo $inbound| jq -c --arg uid "${uid}" --arg flow "${flow}" --arg level "${level}" --arg email "${email}" \ + '.settings.clients += [{"id":$uid,"level":($level|tonumber),"email":$email,"flow":$flow}]'` done # StreamSettings if [ -n "${acceptProxyProtocol}" ]; then - cat $XCONF |jq --arg port "${port}" \ - '( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"sockopt":{"acceptProxyProtocol":true}} ' \ - |sponge $XCONF + inbound=`echo $inbound| jq -c '.settings.streamSettings.sockopt += {"acceptProxyProtocol":true}'` fi # Network settings -cat $XCONF |jq --arg port "${port}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"tcp"} ' \ -|sponge $XCONF +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"network":"tcp"}'` + +# Security settings +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"security":"reality"}'` # Reality settings -cat $XCONF |jq --arg port "${port}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"reality"} ' \ -|sponge $XCONF +inbound=`echo $inbound| jq -c --arg dest "${dest}" --arg pubkey "${pubkey}" --arg prvkey "${prvkey}" \ +'.settings.streamSettings.realitySettings += {"show":true,"dest":"\($dest):443","serverNames":[$dest],"privateKey":$prvkey,"publicKey":$pubkey}'` -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 +# serverNames settings +if [ -n "${serverNames}" ]; then + JserverNames=`printf '%s\n' "${serverNames[@]}"|jq -R|jq -sc` + inbound=`echo $inbound| jq -c --argjson JserverNames "${JserverNames}" '.settings.streamSettings.realitySettings.serverNames += $JserverNames'` +fi -cat $XCONF |jq '( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings.realitySettings.shortIds ) +=$ARGS.positional' \ ---arg port "${port}" --args ${shortIds[@]} \ -|sponge $XCONF +# shortIds settings +JshortIds=`printf '%s\n' "${shortIds[@]}"|jq -R|jq -sc` +inbound=`echo $inbound| jq -c --argjson JshortIds "${JshortIds}" '.settings.streamSettings.realitySettings.shortIds += $JshortIds'` + +# Fallback settings +for fb in "${fallback[@]}" +do + IFS=':'; fopt=(${fb}); fopt=(${fopt[@]}) + fhost="${fopt[0]}"; fport="${fopt[1]}"; fpath="${fopt[2]}" + unset IFS + if [ -z "${fport}" ]; then >&2 echo "Incorrect fallback format: ${fallback}"; usage; exit 1; fi + if [ -z "${fhost}" ]; then fhost="127.0.0.1"; fi + fdest="$fhost:$fport" + Jfb=`jq -nc --arg fdest "${fdest}" --arg fpath "${fpath}" '. |= {"dest":$fdest,"path":$fpath,"xver":1}'` + inbound=`echo $inbound| jq -c --argjson Jfb "${Jfb}" '.settings.fallbacks += [$Jfb]'` +done + +echo $inbound +exit 0 diff --git a/server-ltt.sh b/server-ltt.sh index c22783c..f2edd12 100755 --- a/server-ltt.sh +++ b/server-ltt.sh @@ -3,8 +3,10 @@ DIR=`dirname $0` usage() { - echo "VLESS-TCP-TLS server builder" - echo "Usage: server-ltt ,,,[xtls],[proxy_acpt],,,..." + >&2 echo "VLESS-TCP-TLS server builder" + >&2 echo "Usage: server-ltt ,,,,...,[proxy_acpt],[fallback=host:port:path],[xtls]" + >&2 echo "Fallback format: fallback=[host]<:port>[:/path] Like: 'baidu.com:443:/path', ':1443:/path', ':1443'" + >&2 echo "User format: user|u=[:level:email]" } options=(`echo $1 |tr ',' ' '`) @@ -33,9 +35,6 @@ do u|user) xuser+=("${kv[1]}") ;; - x|xconf) - xconf="${kv[1]}" - ;; xtls) flow="xtls-rprx-vision" ;; @@ -43,93 +42,73 @@ do done if [ -z "${certhome}" ]; then - echo "Error: certhome undefined." - usage - exit 1 + >&2 echo -e "Error: Certhome undefined.\n" + usage; exit 1 fi if [ -z "${domain}" ]; then - echo "Error: domain undefined." - usage - exit 1 -fi - -if [ -n "${flow}" ]; then - flowopt="-f ${flow}" + >&2 echo -e "Error: Domain undefined.\n" + usage; exit 1 fi if [ -z "${port}" ]; then - echo "Error: port undefined." - usage - exit 1 ; + >&2 echo -e "Error: Port undefined.\n" + usage; exit 1 ; fi if [ -z "${xuser}" ]; then - echo "Error: user undefined." - usage - exit 1 + >&2 echo -e "Error: User undefined.\n" + usage; exit 1 fi -if [ -z "${xconf}" ]; then - echo "Error: xconf undefined." - usage - exit 1 -fi +fullchain="${certhome}/${domain}/fullchain.cer" +prvkey="${certhome}/${domain}/${domain}.key" +if [ ! -f "${fullchain}" ]; then >&2 echo "Warning, Fullchain not found: ${fullchain}"; fi +if [ ! -f "${prvkey}" ]; then >&2 echo "Warning, Private key not found: ${prvkey}"; 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 ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo -e "Error: Port number must be numeric.\n"; exit 1; 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 +# inbound frame +inbound=`jq -nc --arg port "${port}" '{"port":$port,"protocol":"vless","settings":{"decryption":"none"}}'` # User settings -for xu in "${xuser[@]}" +for user 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 + IFS=':'; uopt=(${user}); uopt=(${uopt[@]}) + uid="${uopt[0]}"; level="${uopt[1]}"; email="${uopt[2]}" + unset IFS + if [ -z "${uid}" ]; then >&2 echo "Incorrect user format: $user"; usage; exit 1; fi + if [ -z "${level}" ]; then level=0; fi + if [ -z "${email}" ]; then email="${uid}@ltt.$domain"; fi + inbound=`echo $inbound| jq -c --arg uid "${uid}" --arg flow "${flow}" --arg level "${level}" --arg email "${email}" \ + '.settings.clients += [{"id":$uid,"level":($level|tonumber),"email":$email,"flow":$flow}]'` done # StreamSettings if [ -n "${acceptProxyProtocol}" ]; then - cat $XCONF |jq --arg port "${port}" \ - '( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"sockopt":{"acceptProxyProtocol":true}} ' \ - |sponge $XCONF + inbound=`echo $inbound| jq -c '.settings.streamSettings.sockopt += {"acceptProxyProtocol":true}'` fi # Network settings -cat $XCONF |jq --arg port "${port}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"network":"tcp"} ' \ -|sponge $XCONF +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"network":"tcp"}'` -# TLS settings -cat $XCONF |jq --arg port "${port}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"tls"} ' \ -|sponge $XCONF +# Security settings +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"security":"tls"}'` +inbound=`echo $inbound| jq -c --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ +'.settings.streamSettings.tlsSettings += {"certificates":[{"certificateFile":$fullchain,"keyFile":$prvkey}]}'` -cat $XCONF |jq --arg port "${port}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"tlsSettings":{}} ' \ -|sponge $XCONF +# Fallback settings +for fb in "${fallback[@]}" +do + IFS=':'; fopt=(${fb}); fopt=(${fopt[@]}) + fhost="${fopt[0]}"; fport="${fopt[1]}"; fpath="${fopt[2]}" + unset IFS + if [ -z "${fport}" ]; then >&2 echo "Incorrect fallback format: ${fallback}"; usage; exit 1; fi + if [ -z "${fhost}" ]; then fhost="127.0.0.1"; fi + fdest="$fhost:$fport" + Jfb=`jq -nc --arg fdest "${fdest}" --arg fpath "${fpath}" '. |= {"dest":$fdest,"path":$fpath,"xver":1}'` + inbound=`echo $inbound| jq -c --argjson Jfb "${Jfb}" '.settings.fallbacks += [$Jfb]'` +done -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 +echo $inbound +exit 0 \ No newline at end of file diff --git a/server-lwp.sh b/server-lwp.sh index c6f20fa..e1053bb 100755 --- a/server-lwp.sh +++ b/server-lwp.sh @@ -3,8 +3,10 @@ DIR=`dirname $0` usage() { - echo "VLESS-WS-PLAIN server builder" - echo "Usage: server-lwp ,,,,..." + >&2 echo "VLESS-WS-PLAIN server builder" + >&2 echo "Usage: server-lwp ,,,,...,[proxy_acpt],[fallback=host:port:path]" + >&2 echo "Fallback format: fallback=[host]<:port>[:/path] Like: 'baidu.com:443:/path', ':1443:/path', ':1443'" + >&2 echo "User format: user|u=[:level:email]" } options=(`echo $1 |tr ',' ' '`) @@ -15,67 +17,85 @@ do d|domain) domain="${kv[1]}" ;; + f|fallback) + fallback+=("${kv[1]}") + ;; p|port) port="${kv[1]}" ;; + proxy_acpt) + acceptProxyProtocol=true + ;; u|user) xuser+=("${kv[1]}") ;; w|wpath) wspath="${kv[1]}" ;; - x|xconf) - xconf="${kv[1]}" - ;; esac done +if [ -z "${domain}" ]; then + >&2 echo -e "Error: Domain undefined.\n" + usage; exit 1 +fi + if [ -z "${port}" ]; then - echo "Error: port undefined." - usage - exit 1 ; + >&2 echo -e "Error: Port undefined.\n" + usage; exit 1 ; fi if [ -z "${wspath}" ]; then - echo "Error: wspath undefined." - usage - exit 1 + >&2 echo -e "Error: wspath undefined.\n" + usage; exit 1 fi if [ -z "${xuser}" ]; then - echo "Error: user undefined." - usage - exit 1 + >&2 echo -e "Error: User undefined.\n" + 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 -e "Error: Port number must be numeric.\n"; 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 +# inbound frame +inbound=`jq -nc --arg port "${port}" '{"port":$port,"protocol":"vless","settings":{"decryption":"none"}}'` # User settings -for xu in "${xuser[@]}" +for user in "${xuser[@]}" do - cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c lwp.$domain $flowopt | sponge $XCONF + IFS=':'; uopt=(${user}); uopt=(${uopt[@]}) + uid="${uopt[0]}"; level="${uopt[1]}"; email="${uopt[2]}" + unset IFS + if [ -z "${uid}" ]; then >&2 echo "Incorrect user format: $user"; usage; exit 1; fi + if [ -z "${level}" ]; then level=0; fi + if [ -z "${email}" ]; then email="${uid}@lwp.$domain"; fi + inbound=`echo $inbound| jq -c --arg uid "${uid}" --arg flow "${flow}" --arg level "${level}" --arg email "${email}" \ + '.settings.clients += [{"id":$uid,"level":($level|tonumber),"email":$email,"flow":$flow}]'` 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 +# StreamSettings +if [ -n "${acceptProxyProtocol}" ]; then + inbound=`echo $inbound| jq -c '.settings.streamSettings.sockopt += {"acceptProxyProtocol":true}'` +fi -# Plain settings -cat $XCONF |jq --arg port "${port}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"none" } ' \ -|sponge $XCONF +# Network settings +inbound=`echo $inbound| jq -c --arg wspath "${wspath}" '.settings.streamSettings += {"network":"ws","wsSettings":{"path":$wspath}}'` + +# Security settings +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"security":"none"}'` + +# Fallback settings +for fb in "${fallback[@]}" +do + IFS=':'; fopt=(${fb}); fopt=(${fopt[@]}) + fhost="${fopt[0]}"; fport="${fopt[1]}"; fpath="${fopt[2]}" + unset IFS + if [ -z "${fport}" ]; then >&2 echo "Incorrect fallback format: ${fallback}"; usage; exit 1; fi + if [ -z "${fhost}" ]; then fhost="127.0.0.1"; fi + fdest="$fhost:$fport" + Jfb=`jq -nc --arg fdest "${fdest}" --arg fpath "${fpath}" '. |= {"dest":$fdest,"path":$fpath,"xver":1}'` + inbound=`echo $inbound| jq -c --argjson Jfb "${Jfb}" '.settings.fallbacks += [$Jfb]'` +done + +echo $inbound +exit 0 diff --git a/server-lwt.sh b/server-lwt.sh index 16ef467..0220c82 100755 --- a/server-lwt.sh +++ b/server-lwt.sh @@ -3,8 +3,10 @@ DIR=`dirname $0` usage() { - echo "VLESS-WS-TLS server builder" - echo "Usage: server-lwt ,,,,,,..." + >&2 echo "VLESS-WS-TLS server builder" + >&2 echo "Usage: server-lwt ,,,,,...,[proxy_acpt],[fallback=host:port:path],[xtls]" + >&2 echo "Fallback format: fallback=[host]<:port>[:/path] Like: 'baidu.com:443:/path', ':1443:/path', ':1443'" + >&2 echo "User format: user|u=[:level:email]" } options=(`echo $1 |tr ',' ' '`) @@ -27,15 +29,15 @@ do p|port) port="${kv[1]}" ;; + proxy_acpt) + acceptProxyProtocol=true + ;; u|user) xuser+=("${kv[1]}") ;; w|wpath) wspath="${kv[1]}" ;; - x|xconf) - xconf="${kv[1]}" - ;; xtls) flow="xtls-rprx-vision" ;; @@ -43,92 +45,78 @@ do done if [ -z "${certhome}" ]; then - echo "Error: certhome undefined." - usage - exit 1 + >&2 echo -e "Error: Certhome undefined.\n" + usage; exit 1 fi if [ -z "${domain}" ]; then - echo "Error: domain undefined." - usage - exit 1 -fi - -if [ -n "${flow}" ]; then - flowopt="-f ${flow}" + >&2 echo -e "Error: Domain undefined.\n" + usage; exit 1 fi if [ -z "${port}" ]; then - echo "Error: port undefined." - usage - exit 1 ; + >&2 echo -e "Error: Port undefined.\n" + usage; exit 1 ; fi if [ -z "${wspath}" ]; then - echo "Error: wspath undefined." - usage - exit 1 + >&2 echo -e "Error: wspath undefined.\n" + usage; exit 1 fi if [ -z "${xuser}" ]; then - echo "Error: user undefined." - usage - exit 1 + >&2 echo -e "Error: User undefined.\n" + usage; exit 1 fi -if [ -z "${xconf}" ]; then - echo "Error: xconf undefined." - usage - exit 1 -fi +fullchain="${certhome}/${domain}/fullchain.cer" +prvkey="${certhome}/${domain}/${domain}.key" +if [ ! -f "${fullchain}" ]; then >&2 echo "Warning, Fullchain not found: ${fullchain}"; fi +if [ ! -f "${prvkey}" ]; then >&2 echo "Warning, Private key not found: ${prvkey}"; 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 ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo -e "Error: Port number must be numeric.\n"; exit 1; 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 +# inbound frame +inbound=`jq -nc --arg port "${port}" '{"port":$port,"protocol":"vless","settings":{"decryption":"none"}}'` # User settings -for xu in "${xuser[@]}" +for user in "${xuser[@]}" do - cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c lwt.$domain $flowopt | sponge $XCONF + IFS=':'; uopt=(${user}); uopt=(${uopt[@]}) + uid="${uopt[0]}"; level="${uopt[1]}"; email="${uopt[2]}" + unset IFS + if [ -z "${uid}" ]; then >&2 echo "Incorrect user format: $user"; usage; exit 1; fi + if [ -z "${level}" ]; then level=0; fi + if [ -z "${email}" ]; then email="${uid}@lwt.$domain"; fi + inbound=`echo $inbound| jq -c --arg uid "${uid}" --arg flow "${flow}" --arg level "${level}" --arg email "${email}" \ + '.settings.clients += [{"id":$uid,"level":($level|tonumber),"email":$email,"flow":$flow}]'` done +# StreamSettings +if [ -n "${acceptProxyProtocol}" ]; then + inbound=`echo $inbound| jq -c '.settings.streamSettings.sockopt += {"acceptProxyProtocol":true}'` +fi + +# Network settings +inbound=`echo $inbound| jq -c --arg wspath "${wspath}" '.settings.streamSettings += {"network":"ws","wsSettings":{"path":$wspath}}'` + +# Security settings +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"security":"tls"}'` +inbound=`echo $inbound| jq -c --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ +'.settings.streamSettings.tlsSettings += {"certificates":[{"certificateFile":$fullchain,"keyFile":$prvkey}]}'` + # Fallback settings for fb in "${fallback[@]}" do - cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF + IFS=':'; fopt=(${fb}); fopt=(${fopt[@]}) + fhost="${fopt[0]}"; fport="${fopt[1]}"; fpath="${fopt[2]}" + unset IFS + if [ -z "${fport}" ]; then >&2 echo "Incorrect fallback format: ${fallback}"; usage; exit 1; fi + if [ -z "${fhost}" ]; then fhost="127.0.0.1"; fi + fdest="$fhost:$fport" + Jfb=`jq -nc --arg fdest "${fdest}" --arg fpath "${fpath}" '. |= {"dest":$fdest,"path":$fpath,"xver":1}'` + inbound=`echo $inbound| jq -c --argjson Jfb "${Jfb}" '.settings.fallbacks += [$Jfb]'` 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 +echo $inbound +exit 0 diff --git a/server-mtt.sh b/server-mtt.sh index 40c34be..c74be04 100755 --- a/server-mtt.sh +++ b/server-mtt.sh @@ -3,8 +3,10 @@ DIR=`dirname $0` usage() { - echo "VMESS-TCP-TLS server builder" - echo "Usage: server-mtt ,,,,,..." + >&2 echo "VMESS-TCP-TLS server builder" + >&2 echo "Usage: server-mtt ,,,,...,[proxy_acpt],[fallback=host:port:path],[xtls]" + >&2 echo "Fallback format: fallback=[host]<:port>[:/path] Like: 'baidu.com:443:/path', ':1443:/path', ':1443'" + >&2 echo "User format: user|u=[:level:email]" } options=(`echo $1 |tr ',' ' '`) @@ -27,12 +29,12 @@ do p|port) port="${kv[1]}" ;; + proxy_acpt) + acceptProxyProtocol=true + ;; u|user) xuser+=("${kv[1]}") ;; - x|xconf) - xconf="${kv[1]}" - ;; xtls) flow="xtls-rprx-vision" ;; @@ -40,86 +42,73 @@ do done if [ -z "${certhome}" ]; then - echo "Error: certhome undefined." - usage - exit 1 + >&2 echo -e "Error: Certhome undefined.\n" + usage; exit 1 fi if [ -z "${domain}" ]; then - echo "Error: domain undefined." - usage - exit 1 -fi - -if [ -n "${flow}" ]; then - flowopt="-f ${flow}" + >&2 echo -e "Error: Domain undefined.\n" + usage; exit 1 fi if [ -z "${port}" ]; then - echo "Error: port undefined." - usage - exit 1 ; + >&2 echo -e "Error: Port undefined.\n" + usage; exit 1 ; fi if [ -z "${xuser}" ]; then - echo "Error: user undefined." - usage - exit 1 + >&2 echo -e "Error: User undefined.\n" + usage; exit 1 fi -if [ -z "${xconf}" ]; then - echo "Error: xconf undefined." - usage - exit 1 -fi +fullchain="${certhome}/${domain}/fullchain.cer" +prvkey="${certhome}/${domain}/${domain}.key" +if [ ! -f "${fullchain}" ]; then >&2 echo "Warning, Fullchain not found: ${fullchain}"; fi +if [ ! -f "${prvkey}" ]; then >&2 echo "Warning, Private key not found: ${prvkey}"; 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 ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo -e "Error: Port number must be numeric.\n"; exit 1; 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 +# inbound frame +inbound=`jq -nc --arg port "${port}" '{"port":$port,"protocol":"vmess","settings":{"decryption":"none"}}'` # User settings -for xu in "${xuser[@]}" +for user in "${xuser[@]}" do - cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c mtt.$dest $flowopt | sponge $XCONF + IFS=':'; uopt=(${user}); uopt=(${uopt[@]}) + uid="${uopt[0]}"; level="${uopt[1]}"; email="${uopt[2]}" + unset IFS + if [ -z "${uid}" ]; then >&2 echo "Incorrect user format: $user"; usage; exit 1; fi + if [ -z "${level}" ]; then level=0; fi + if [ -z "${email}" ]; then email="${uid}@mtt.$domain"; fi + inbound=`echo $inbound| jq -c --arg uid "${uid}" --arg flow "${flow}" --arg level "${level}" --arg email "${email}" \ + '.settings.clients += [{"id":$uid,"level":($level|tonumber),"email":$email,"flow":$flow}]'` done +# StreamSettings +if [ -n "${acceptProxyProtocol}" ]; then + inbound=`echo $inbound| jq -c '.settings.streamSettings.sockopt += {"acceptProxyProtocol":true}'` +fi + +# Network settings +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"network":"tcp"}'` + +# Security settings +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"security":"tls"}'` +inbound=`echo $inbound| jq -c --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ +'.settings.streamSettings.tlsSettings += {"certificates":[{"certificateFile":$fullchain,"keyFile":$prvkey}]}'` + # Fallback settings for fb in "${fallback[@]}" do - cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF + IFS=':'; fopt=(${fb}); fopt=(${fopt[@]}) + fhost="${fopt[0]}"; fport="${fopt[1]}"; fpath="${fopt[2]}" + unset IFS + if [ -z "${fport}" ]; then >&2 echo "Incorrect fallback format: ${fallback}"; usage; exit 1; fi + if [ -z "${fhost}" ]; then fhost="127.0.0.1"; fi + fdest="$fhost:$fport" + Jfb=`jq -nc --arg fdest "${fdest}" --arg fpath "${fpath}" '. |= {"dest":$fdest,"path":$fpath,"xver":1}'` + inbound=`echo $inbound| jq -c --argjson Jfb "${Jfb}" '.settings.fallbacks += [$Jfb]'` 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 +echo $inbound +exit 0 diff --git a/server-mwp.sh b/server-mwp.sh index 65ed192..17ca14e 100755 --- a/server-mwp.sh +++ b/server-mwp.sh @@ -3,8 +3,10 @@ DIR=`dirname $0` usage() { - echo "VMESS-WS-PLAIN server builder" - echo "Usage: server-mwp ,,,,..." + >&2 echo "VMESS-WS-PLAIN server builder" + >&2 echo "Usage: server-mwp ,,,,...,[proxy_acpt],[fallback=host:port:path]" + >&2 echo "Fallback format: fallback=[host]<:port>[:/path] Like: 'baidu.com:443:/path', ':1443:/path', ':1443'" + >&2 echo "User format: user|u=[:level:email]" } options=(`echo $1 |tr ',' ' '`) @@ -15,67 +17,88 @@ do d|domain) domain="${kv[1]}" ;; + f|fallback) + fallback+=("${kv[1]}") + ;; p|port) port="${kv[1]}" ;; + proxy_acpt) + acceptProxyProtocol=true + ;; u|user) xuser+=("${kv[1]}") ;; w|wpath) wspath="${kv[1]}" ;; - x|xconf) - xconf="${kv[1]}" - ;; esac done +if [ -z "${domain}" ]; then + >&2 echo -e "Error: Domain undefined.\n" + usage; exit 1 +fi + if [ -z "${port}" ]; then - echo "Error: port undefined." - usage - exit 1 ; + >&2 echo -e "Error: Port undefined.\n" + usage; exit 1 ; fi if [ -z "${wspath}" ]; then - echo "Error: wspath undefined." - usage - exit 1 + >&2 echo -e "Error: wspath undefined.\n" + usage; exit 1 fi if [ -z "${xuser}" ]; then - echo "Error: user undefined." - usage - exit 1 + >&2 echo -e "Error: User undefined.\n" + 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.\n"; 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 +# inbound frame +inbound=`jq -nc --arg port "${port}" '{"port":$port,"protocol":"vmess","settings":{"decryption":"none"}}'` # User settings -for xu in "${xuser[@]}" +for user in "${xuser[@]}" do - cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c mwp.$domain $flowopt | sponge $XCONF + IFS=':'; uopt=(${user}); uopt=(${uopt[@]}) + uid="${uopt[0]}"; level="${uopt[1]}"; email="${uopt[2]}" + unset IFS + if [ -z "${uid}" ]; then >&2 echo "Incorrect user format: $user"; usage; exit 1; fi + if [ -z "${level}" ]; then level=0; fi + if [ -z "${email}" ]; then email="${uid}@mwp.$domain"; fi + inbound=`echo $inbound| jq -c --arg uid "${uid}" --arg flow "${flow}" --arg level "${level}" --arg email "${email}" \ + '.settings.clients += [{"id":$uid,"level":($level|tonumber),"email":$email,"flow":$flow}]'` 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 +# StreamSettings +if [ -n "${acceptProxyProtocol}" ]; then + inbound=`echo $inbound| jq -c '.settings.streamSettings.sockopt += {"acceptProxyProtocol":true}'` +fi -# Plain settings -cat $XCONF |jq --arg port "${port}" \ -'( .inbounds[] | select(.port == ($port|tonumber)) | .streamSettings ) += {"security":"none" } ' \ -|sponge $XCONF +# Network settings +inbound=`echo $inbound| jq -c --arg wspath "${wspath}" '.settings.streamSettings += {"network":"ws","wsSettings":{"path":$wspath}}'` + +# Security settings +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"security":"none"}'` + +# Fallback settings +for fb in "${fallback[@]}" +do + IFS=':'; fopt=(${fb}); fopt=(${fopt[@]}) + fhost="${fopt[0]}"; fport="${fopt[1]}"; fpath="${fopt[2]}" + unset IFS + if [ -z "${fport}" ]; then + >&2 echo "Incorrect fallback format: ${fallback}" + usage; exit 1 + fi + if [ -z "${fhost}" ]; then fhost="127.0.0.1"; fi + fdest="$fhost:$fport" + Jfb=`jq -nc --arg fdest "${fdest}" --arg fpath "${fpath}" '. |= {"dest":$fdest,"path":$fpath,"xver":1}'` + inbound=`echo $inbound| jq -c --argjson Jfb "${Jfb}" '.settings.fallbacks += [$Jfb]'` +done + +echo $inbound +exit 0 diff --git a/server-mwt.sh b/server-mwt.sh index c5b933d..d790450 100755 --- a/server-mwt.sh +++ b/server-mwt.sh @@ -3,8 +3,10 @@ DIR=`dirname $0` usage() { - echo "VMESS-WS-TLS server builder" - echo "Usage: server-mwt ,,,,,,..." + >&2 echo "VMESS-WS-TLS server builder" + >&2 echo "Usage: server-mwt ,,,,,...,[proxy_acpt],[fallback=host:port:path],[xtls]" + >&2 echo "Fallback format: fallback=[host]<:port>[:/path] Like: 'baidu.com:443:/path', ':1443:/path', ':1443'" + >&2 echo "User format: user|u=[:level:email]" } options=(`echo $1 |tr ',' ' '`) @@ -27,15 +29,15 @@ do p|port) port="${kv[1]}" ;; + proxy_acpt) + acceptProxyProtocol=true + ;; u|user) xuser+=("${kv[1]}") ;; w|wpath) wspath="${kv[1]}" ;; - x|xconf) - xconf="${kv[1]}" - ;; xtls) flow="xtls-rprx-vision" ;; @@ -43,92 +45,81 @@ do done if [ -z "${certhome}" ]; then - echo "Error: certhome undefined." - usage - exit 1 + >&2 echo -e "Error: Certhome undefined.\n" + usage; exit 1 fi if [ -z "${domain}" ]; then - echo "Error: domain undefined." - usage - exit 1 -fi - -if [ -n "${flow}" ]; then - flowopt="-f ${flow}" + >&2 echo -e "Error: Domain undefined.\n" + usage; exit 1 fi if [ -z "${port}" ]; then - echo "Error: port undefined." - usage - exit 1 ; + >&2 echo -e "Error: Port undefined.\n" + usage; exit 1 ; fi if [ -z "${wspath}" ]; then - echo "Error: wspath undefined." - usage - exit 1 + >&2 echo -e "Error: wspath undefined.\n" + usage; exit 1 fi if [ -z "${xuser}" ]; then - echo "Error: user undefined." - usage - exit 1 + >&2 echo -e "Error: User undefined.\n" + usage; exit 1 fi -if [ -z "${xconf}" ]; then - echo "Error: xconf undefined." - usage - exit 1 -fi +fullchain="${certhome}/${domain}/fullchain.cer" +prvkey="${certhome}/${domain}/${domain}.key" +if [ ! -f "${fullchain}" ]; then >&2 echo "Warning, Fullchain not found: ${fullchain}"; fi +if [ ! -f "${prvkey}" ]; then >&2 echo "Warning, Private key not found: ${prvkey}"; 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 ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo -e "Error: Port number must be numeric.\n"; exit 1; 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 +# inbound frame +inbound=`jq -nc --arg port "${port}" '{"port":$port,"protocol":"vmess","settings":{"decryption":"none"}}'` # User settings -for xu in "${xuser[@]}" +for user in "${xuser[@]}" do - cat $XCONF | ${DIR}/adduser.sh -p $port -u ${xu} -c mwt.$domain $flowopt | sponge $XCONF + IFS=':'; uopt=(${user}); uopt=(${uopt[@]}) + uid="${uopt[0]}"; level="${uopt[1]}"; email="${uopt[2]}" + unset IFS + if [ -z "${uid}" ]; then >&2 echo "Incorrect user format: $user"; usage; exit 1; fi + if [ -z "${level}" ]; then level=0; fi + if [ -z "${email}" ]; then email="${uid}@mwt.$domain"; fi + inbound=`echo $inbound| jq -c --arg uid "${uid}" --arg flow "${flow}" --arg level "${level}" --arg email "${email}" \ + '.settings.clients += [{"id":$uid,"level":($level|tonumber),"email":$email,"flow":$flow}]'` done +# StreamSettings +if [ -n "${acceptProxyProtocol}" ]; then + inbound=`echo $inbound| jq -c '.settings.streamSettings.sockopt += {"acceptProxyProtocol":true}'` +fi + +# Network settings +inbound=`echo $inbound| jq -c --arg wspath "${wspath}" '.settings.streamSettings += {"network":"ws","wsSettings":{"path":$wspath}}'` + +# Security settings +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"security":"tls"}'` +inbound=`echo $inbound| jq -c --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ +'.settings.streamSettings.tlsSettings += {"certificates":[{"certificateFile":$fullchain,"keyFile":$prvkey}]}'` + # Fallback settings for fb in "${fallback[@]}" do - cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF + IFS=':'; fopt=(${fb}); fopt=(${fopt[@]}) + fhost="${fopt[0]}"; fport="${fopt[1]}"; fpath="${fopt[2]}" + unset IFS + if [ -z "${fport}" ]; then + >&2 echo "Incorrect fallback format: ${fallback}" + usage; exit 1 + fi + if [ -z "${fhost}" ]; then fhost="127.0.0.1"; fi + fdest="$fhost:$fport" + Jfb=`jq -nc --arg fdest "${fdest}" --arg fpath "${fpath}" '. |= {"dest":$fdest,"path":$fpath,"xver":1}'` + inbound=`echo $inbound| jq -c --argjson Jfb "${Jfb}" '.settings.fallbacks += [$Jfb]'` 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 +echo $inbound +exit 0 diff --git a/server-nginx.sh b/server-nginx.sh index 3d42d08..d9e8fa2 100755 --- a/server-nginx.sh +++ b/server-nginx.sh @@ -20,23 +20,23 @@ if [ $? != 0 ] ; then usage; exit 1 ; fi eval set -- "$TEMP" while true ; do case "$1" in - # Multiple Nginx domain servers Allowed -n|--ng-server) + # Multiple Nginx domain servers Allowed NGSVR+=("$2") shift 2 ;; - # Multiple Nginx proxy locations Allowed -x|--ng-proxy) + # Multiple Nginx proxy locations Allowed NGPROXY+=("$2") shift 2 ;; - # Only SINGLE Stream server Allowed -s|--st-server) + # Only SINGLE Stream server Allowed STSVR="$2" shift 2 ;; - # Multiple Nginx SNI map items Allowed -m|--st-map) + # Multiple Nginx SNI map items Allowed STMAP+=("$2") shift 2 ;; diff --git a/server-ttt.sh b/server-ttt.sh index 3682586..3aa8047 100755 --- a/server-ttt.sh +++ b/server-ttt.sh @@ -3,8 +3,10 @@ DIR=`dirname $0` usage() { - echo "TROJAN-TCP-TLS server builder" - echo "Usage: server-ttt ,,,,,..." + >&2 echo "TROJAN-TCP-TLS server builder" + >&2 echo "Usage: server-ttt ,,,,...,[proxy_acpt],[fallback=host:port:path],[xtls]" + >&2 echo "Fallback format: fallback=[host]<:port>[:/path] Like: 'baidu.com:443:/path', ':1443:/path', ':1443'" + >&2 echo "User format: user|u=[:level:email]" } options=(`echo $1 |tr ',' ' '`) @@ -27,12 +29,12 @@ do p|port) port="${kv[1]}" ;; + proxy_acpt) + acceptProxyProtocol=true + ;; u|user) xuser+=("${kv[1]}") ;; - x|xconf) - xconf="${kv[1]}" - ;; xtls) flow="xtls-rprx-vision" ;; @@ -40,86 +42,73 @@ do done if [ -z "${certhome}" ]; then - echo "Error: certhome undefined." - usage - exit 1 + >&2 echo -e "Error: Certhome undefined.\n" + usage; exit 1 fi if [ -z "${domain}" ]; then - echo "Error: domain undefined." - usage - exit 1 -fi - -if [ -n "${flow}" ]; then - flowopt="-f ${flow}" + >&2 echo -e "Error: Domain undefined.\n" + usage; exit 1 fi if [ -z "${port}" ]; then - echo "Error: port undefined." - usage - exit 1 ; + >&2 echo -e "Error: Port undefined.\n" + usage; exit 1 ; fi if [ -z "${xuser}" ]; then - echo "Error: user undefined." - usage - exit 1 + >&2 echo -e "Error: User undefined.\n" + usage; exit 1 fi -if [ -z "${xconf}" ]; then - echo "Error: xconf undefined." - usage - exit 1 -fi +fullchain="${certhome}/${domain}/fullchain.cer" +prvkey="${certhome}/${domain}/${domain}.key" +if [ ! -f "${fullchain}" ]; then >&2 echo "Warning, Fullchain not found: ${fullchain}"; fi +if [ ! -f "${prvkey}" ]; then >&2 echo "Warning, Private key not found: ${prvkey}"; 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 ! [ "${port}" -eq "${port}" ] 2>/dev/null; then >&2 echo -e "Error: Port number must be numeric.\n"; exit 1; 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 +# inbound frame +inbound=`jq -nc --arg port "${port}" '{"port":$port,"protocol":"trojan","settings":{"decryption":"none"}}'` # User settings -for xu in "${xuser[@]}" +for user in "${xuser[@]}" do - cat $XCONF | ${DIR}/addusertj.sh -p $port -u ${xu} -c ttt.$dest $flowopt | sponge $XCONF + IFS=':'; uopt=(${user}); uopt=(${uopt[@]}) + uid="${uopt[0]}"; level="${uopt[1]}"; email="${uopt[2]}" + unset IFS + if [ -z "${uid}" ]; then >&2 echo "Incorrect user format: $user"; usage; exit 1; fi + if [ -z "${level}" ]; then level=0; fi + if [ -z "${email}" ]; then email="${uid}@ttt.$domain"; fi + inbound=`echo $inbound| jq -c --arg uid "${uid}" --arg flow "${flow}" --arg level "${level}" --arg email "${email}" \ + '.settings.clients += [{"password":$uid,"level":($level|tonumber),"email":$email,"flow":$flow}]'` done +# StreamSettings +if [ -n "${acceptProxyProtocol}" ]; then + inbound=`echo $inbound| jq -c '.settings.streamSettings.sockopt += {"acceptProxyProtocol":true}'` +fi + +# Network settings +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"network":"tcp"}'` + +# Security settings +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"security":"tls"}'` +inbound=`echo $inbound| jq -c --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ +'.settings.streamSettings.tlsSettings += {"certificates":[{"certificateFile":$fullchain,"keyFile":$prvkey}]}'` + # Fallback settings for fb in "${fallback[@]}" do - cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF + IFS=':'; fopt=(${fb}); fopt=(${fopt[@]}) + fhost="${fopt[0]}"; fport="${fopt[1]}"; fpath="${fopt[2]}" + unset IFS + if [ -z "${fport}" ]; then >&2 echo "Incorrect fallback format: ${fallback}"; usage; exit 1; fi + if [ -z "${fhost}" ]; then fhost="127.0.0.1"; fi + fdest="$fhost:$fport" + Jfb=`jq -nc --arg fdest "${fdest}" --arg fpath "${fpath}" '. |= {"dest":$fdest,"path":$fpath,"xver":1}'` + inbound=`echo $inbound| jq -c --argjson Jfb "${Jfb}" '.settings.fallbacks += [$Jfb]'` 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 +echo $inbound +exit 0 diff --git a/server-twp.sh b/server-twp.sh index 97b9302..01f5104 100755 --- a/server-twp.sh +++ b/server-twp.sh @@ -3,8 +3,111 @@ DIR=`dirname $0` usage() { - echo "TROJAN-WS-PLAIN server builder" - echo "Usage: server-twp ,,,,..." + >&2 echo "TROJAN-WS-PLAIN server builder" + >&2 echo "Usage: server-twp ,,,,...,[proxy_acpt],[fallback=host:port:path]" + >&2 echo "Fallback format: fallback=[host]<:port>[:/path] Like: 'baidu.com:443:/path', ':1443:/path', ':1443'" + >&2 echo "User format: user=[:level:email]" +} + +options=(`echo $1 |tr ',' ' '`) +for option in "${options[@]}" +do + kv=(`echo $option |tr '=' ' '`) + case "${kv[0]}" in + d|domain) + domain="${kv[1]}" + ;; + f|fallback) + fallback+=("${kv[1]}") + ;; + p|port) + port="${kv[1]}" + ;; + proxy_acpt) + acceptProxyProtocol=true + ;; + u|user) + xuser+=("${kv[1]}") + ;; + w|wpath) + wspath="${kv[1]}" + ;; + esac +done + +if [ -z "${domain}" ]; then + >&2 echo "Error: Domain undefined." + usage; exit 1 +fi + +if [ -z "${port}" ]; then + >&2 echo "Error: Port undefined." + usage; exit 1 ; +fi + +if [ -z "${wspath}" ]; then + >&2 echo "Error: wspath undefined." + usage; exit 1 +fi + +if [ -z "${xuser}" ]; then + >&2 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 + +# inbound frame +inbound=`jq -nc --arg port "${port}" '{"port":$port,"protocol":"trojan","settings":{"decryption":"none"}}'` + +# User settings +for user in "${xuser[@]}" +do + IFS=':'; uopt=(${user}); uopt=(${uopt[@]}) + uid="${uopt[0]}"; level="${uopt[1]}"; email="${uopt[2]}" + unset IFS + if [ -z "${uid}" ]; then >&2 echo "Incorrect user format: $user"; usage; exit 1; fi + if [ -z "${level}" ]; then level=0; fi + if [ -z "${email}" ]; then email="${uid}@twp.$domain"; fi + inbound=`echo $inbound| jq -c --arg uid "${uid}" --arg flow "${flow}" --arg level "${level}" --arg email "${email}" \ + '.settings.clients += [{"password":$uid,"level":($level|tonumber),"email":$email,"flow":$flow}]'` +done + +# StreamSettings +if [ -n "${acceptProxyProtocol}" ]; then + inbound=`echo $inbound| jq -c '.settings.streamSettings.sockopt += {"acceptProxyProtocol":true}'` +fi + +# Network settings +inbound=`echo $inbound| jq -c --arg wspath "${wspath}" '.settings.streamSettings += {"network":"ws","wsSettings":{"path":$wspath}}'` + +# Security settings +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"security":"none"}'` + +# Fallback settings +for fb in "${fallback[@]}" +do + IFS=':'; fopt=(${fb}); fopt=(${fopt[@]}) + fhost="${fopt[0]}"; fport="${fopt[1]}"; fpath="${fopt[2]}" + unset IFS + if [ -z "${fport}" ]; then + >&2 echo "Incorrect fallback format: ${fallback}" + usage; exit 1 + fi + if [ -z "${fhost}" ]; then fhost="127.0.0.1"; fi + fdest="$fhost:$fport" + Jfb=`jq -nc --arg fdest "${fdest}" --arg fpath "${fpath}" '. |= {"dest":$fdest,"path":$fpath,"xver":1}'` + inbound=`echo $inbound| jq -c --argjson Jfb "${Jfb}" '.settings.fallbacks += [$Jfb]'` +done + +echo $inbound +exit 0 + + + + + + } options=(`echo $1 |tr ',' ' '`) @@ -61,7 +164,7 @@ XCONF=$xconf 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 +=[{"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 diff --git a/server-twt.sh b/server-twt.sh index 6a13a59..248e607 100755 --- a/server-twt.sh +++ b/server-twt.sh @@ -3,8 +3,10 @@ DIR=`dirname $0` usage() { - echo "TROJAN-WS-TLS server builder" - echo "Usage: server-twt ,,,,,,..." + >&2 echo "TROJAN-WS-TLS server builder" + >&2 echo "Usage: server-twt ,,,,,...,[proxy_acpt],[fallback=host:port:path],[xtls]" + >&2 echo "Fallback format: fallback=[host]<:port>[:/path] Like: 'baidu.com:443:/path', ':1443:/path', ':1443'" + >&2 echo "User format: user=[:level:email]" } options=(`echo $1 |tr ',' ' '`) @@ -27,15 +29,15 @@ do p|port) port="${kv[1]}" ;; + proxy_acpt) + acceptProxyProtocol=true + ;; u|user) xuser+=("${kv[1]}") ;; w|wpath) wspath="${kv[1]}" ;; - x|xconf) - xconf="${kv[1]}" - ;; xtls) flow="xtls-rprx-vision" ;; @@ -43,92 +45,81 @@ do done if [ -z "${certhome}" ]; then - echo "Error: certhome undefined." - usage - exit 1 + >&2 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}" + >&2 echo "Error: Domain undefined." + usage; exit 1 fi if [ -z "${port}" ]; then - echo "Error: port undefined." - usage - exit 1 ; + >&2 echo "Error: Port undefined." + usage; exit 1 ; fi if [ -z "${wspath}" ]; then - echo "Error: wspath undefined." - usage - exit 1 + >&2 echo "Error: wspath undefined." + usage; exit 1 fi if [ -z "${xuser}" ]; then - echo "Error: user undefined." - usage - exit 1 + >&2 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 +fullchain="${certhome}/${domain}/fullchain.cer" +prvkey="${certhome}/${domain}/${domain}.key" +if [ ! -f "${fullchain}" ]; then >&2 echo "Warning, Fullchain not found: ${fullchain}"; fi +if [ ! -f "${prvkey}" ]; then >&2 echo "Warning, Private key not found: ${prvkey}"; 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 +# inbound frame +inbound=`jq -nc --arg port "${port}" '{"port":$port,"protocol":"trojan","settings":{"decryption":"none"}}'` # User settings -for xu in "${xuser[@]}" +for user in "${xuser[@]}" do - cat $XCONF | ${DIR}/addusertj.sh -p $port -u ${xu} -c twt.$domain $flowopt | sponge $XCONF + IFS=':'; uopt=(${user}); uopt=(${uopt[@]}) + uid="${uopt[0]}"; level="${uopt[1]}"; email="${uopt[2]}" + unset IFS + if [ -z "${uid}" ]; then >&2 echo "Incorrect user format: $user"; usage; exit 1; fi + if [ -z "${level}" ]; then level=0; fi + if [ -z "${email}" ]; then email="${uid}@twt.$domain"; fi + inbound=`echo $inbound| jq -c --arg uid "${uid}" --arg flow "${flow}" --arg level "${level}" --arg email "${email}" \ + '.settings.clients += [{"password":$uid,"level":($level|tonumber),"email":$email,"flow":$flow}]'` done +# StreamSettings +if [ -n "${acceptProxyProtocol}" ]; then + inbound=`echo $inbound| jq -c '.settings.streamSettings.sockopt += {"acceptProxyProtocol":true}'` +fi + +# Network settings +inbound=`echo $inbound| jq -c --arg wspath "${wspath}" '.settings.streamSettings += {"network":"ws","wsSettings":{"path":$wspath}}'` + +# Security settings +inbound=`echo $inbound| jq -c '.settings.streamSettings += {"security":"tls"}'` +inbound=`echo $inbound| jq -c --arg fullchain "${fullchain}" --arg prvkey "${prvkey}" \ +'.settings.streamSettings.tlsSettings += {"certificates":[{"certificateFile":$fullchain,"keyFile":$prvkey}]}'` + # Fallback settings for fb in "${fallback[@]}" do - cat $XCONF |${DIR}/fallback.sh -p $port -f ${fb} | sponge $XCONF + IFS=':'; fopt=(${fb}); fopt=(${fopt[@]}) + fhost="${fopt[0]}"; fport="${fopt[1]}"; fpath="${fopt[2]}" + unset IFS + if [ -z "${fport}" ]; then + >&2 echo "Incorrect fallback format: ${fallback}" + usage; exit 1 + fi + if [ -z "${fhost}" ]; then fhost="127.0.0.1"; fi + fdest="$fhost:$fport" + Jfb=`jq -nc --arg fdest "${fdest}" --arg fpath "${fpath}" '. |= {"dest":$fdest,"path":$fpath,"xver":1}'` + inbound=`echo $inbound| jq -c --argjson Jfb "${Jfb}" '.settings.fallbacks += [$Jfb]'` 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 +echo $inbound +exit 0