From 013ce483a8e90b5a7d13d67d5d26ca098fecf7d6 Mon Sep 17 00:00:00 2001 From: SkyperTHC Date: Mon, 14 Aug 2023 11:22:59 +0100 Subject: [PATCH] 0.4.9rc1 --- ChangeLog | 10 + Makefile | 3 +- config/etc/nginx/nginx-rpc.conf | 11 + config/etc/redis/redis.conf | 1 - contrib/cronjob | 2 +- contrib/sfwg | 31 +-- docker-compose.yml | 10 +- encfsd/encfsd.sh | 6 + guest/Dockerfile | 27 ++- guest/Makefile | 10 +- guest/fs-root/etc/shellrc | 16 +- guest/fs-root/sf/bin/geoip | 30 ++- guest/setup.sh | 3 + host/fs-root/bin/segfaultsh | 17 +- host/mk_sshd.sh | 2 +- host/sf-sshd.patch | 55 +++-- master/cgi-bin/rpc | 363 ++++++++++++++++++++++++-------- provision/env.example | 6 +- provision/init-linux.sh | 5 +- router/init.sh | 5 +- sfbin/funcs_admin.sh | 29 +++ sfbin/sf | 27 ++- 22 files changed, 493 insertions(+), 176 deletions(-) mode change 100644 => 100755 config/etc/redis/redis.conf diff --git a/ChangeLog b/ChangeLog index 36286e7..ba68358 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +0.4.9p1 - 2023-09 + * a2enmod for php8.2 (thanks matthew) + +0.4.9a1 - 2023-08-13 + * geoiphn, asn, reboot, shutdown, pwncat-cs, aws + * inotify limit + * token fix for USER_FS_SIZE + * CG only kill while LOAD goes up + * Outgoing WireGuard (beta) + 0.4.8p1 - 2023-06-21 * Better TOKEN support * Fix disconnect when last-server-warning diff --git a/Makefile b/Makefile index bf5aea1..401b51f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VER := 0.4.8p2 +VER := 0.4.9p1 all: make -C router @@ -44,6 +44,7 @@ FILES_GUEST += "segfault-$(VER)/guest/fs-root/sf/bin/startxvnc" FILES_GUEST += "segfault-$(VER)/guest/fs-root/sf/bin/startxweb" FILES_GUEST += "segfault-$(VER)/guest/fs-root/sf/bin/startfb" FILES_GUEST += "segfault-$(VER)/guest/fs-root/sf/bin/geoip" +FILES_GUEST += "segfault-$(VER)/guest/fs-root/sf/bin/geoiphn" FILES_GUEST += "segfault-$(VER)/guest/fs-root/sf/bin/pkg-install.sh" FILES_GUEST += "segfault-$(VER)/guest/fs-root/etc/rc.local-example" FILES_GUEST += "segfault-$(VER)/guest/fs-root/etc/vim/vimrc.local" diff --git a/config/etc/nginx/nginx-rpc.conf b/config/etc/nginx/nginx-rpc.conf index 1df732c..7a70229 100644 --- a/config/etc/nginx/nginx-rpc.conf +++ b/config/etc/nginx/nginx-rpc.conf @@ -70,6 +70,9 @@ http { location / { try_files $uri $uri/ = 404; + rewrite /net /net/; + rewrite /wg /wg/; + rewrite /dmesg /dmesg/; location ~* ^/net/.* { fastcgi_param REMOTE_ADDR $remote_addr; @@ -79,6 +82,14 @@ http { fastcgi_param SCRIPT_FILENAME /cgi-bin/rpc; fastcgi_pass unix:/dev/shm/sf/master/fcgiwrap.socket; } + location ~* ^/wg/.* { + fastcgi_param REMOTE_ADDR $remote_addr; + fastcgi_param REQUEST_URI $request_uri; + fastcgi_param REQUEST_BODY $request_body; + fastcgi_param FCGI_CMD wg; + fastcgi_param SCRIPT_FILENAME /cgi-bin/rpc; + fastcgi_pass unix:/dev/shm/sf/master/fcgiwrap.socket; + } location ~* ^/dmesg/ { fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REQUEST_URI $request_uri; diff --git a/config/etc/redis/redis.conf b/config/etc/redis/redis.conf old mode 100644 new mode 100755 index cba6e34..ab822c2 --- a/config/etc/redis/redis.conf +++ b/config/etc/redis/redis.conf @@ -7,4 +7,3 @@ rename-command MONITOR "" rename-command COMMAND "" unixsocketperm 777 unixsocket /redis-sock/redis.sock - diff --git a/contrib/cronjob b/contrib/cronjob index 1436722..e03df31 100755 --- a/contrib/cronjob +++ b/contrib/cronjob @@ -1,6 +1,6 @@ #! /usr/bin/env bash -# Run regular maintenance jobs +# Run regular maintenance jobs in host's crontab after 'sf up' has been started SF_MV_EXIT_FN="/sf/data/share/relay-exit-nodes-mullvad.txt" SF_MV_RELAY_FN="/sf/data/share/proxies.txt" diff --git a/contrib/sfwg b/contrib/sfwg index 550f88d..2f81382 100755 --- a/contrib/sfwg +++ b/contrib/sfwg @@ -101,12 +101,6 @@ x2data() [[ -z $ADDRES6 ]] && ADDRES6="fd:16::1/128" [[ -z $PEER_ADDRESS ]] && PEER_ADDRESS="172.16.0.0/16" [[ -z $PEER_ADDRES6 ]] && PEER_ADDRES6="fd:16::0/104" - - ### SF < 0.4.7 compatible - # [[ -z $ADDRESS ]] && ADDRESS="192.168.0.1/32" - # [[ -z $ADDRES6 ]] && ADDRES6="fd::1/128" - # [[ -z $PEER_ADDRESS ]] && PEER_ADDRESS="192.168.0.0/16" - # [[ -z $PEER_ADDRES6 ]] && PEER_ADDRES6="fd::0/104" } # Delete any IPT rule and add new one @@ -352,10 +346,6 @@ wt_up() "${cmd_checkrunning[@]}" && ERREXIT 255 "${CDM}Wiretap${CN} is already running. To stop: ${CDC}killall '${killname}'${CN}" fi - # command -v wiretap >/dev/null || { - # export PATH=".:$PATH" - # [[ ! -e wiretap ]] && wt_dl - # } [[ -d wiretap ]] && { ERR "Directory ${CDY}./wiretap${CN} is in the way"; return 255; } if [[ -f wiretap ]]; then WARN "Using existing ${CDM}./wiretap${CN}" @@ -366,18 +356,17 @@ wt_up() [[ -n $WITH_IPV6 ]] && peer_addr+=",${PEER_ADDRES6}" # CWD may have changed by wt_dl - # ./wiretap configure --simple unset ENVSTR - if [[ $SF_VER -eq 1 ]]; then - addenv WIRETAP_INTERFACE_PRIVATEKEY "$PRIV" - addenv WIRETAP_PEER_PUBLICKEY "${PEER}" - addenv WIRETAP_PEER_ENDPOINT "${EP}" - else - addenv WIRETAP_RELAY_INTERFACE_PRIVATEKEY "${PRIV}" - addenv WIRETAP_RELAY_PEER_PUBLICKEY "${PEER}" - addenv WIRETAP_RELAY_PEER_ENDPOINT "${EP}" - addenv WIRETAP_SIMPLE "true" - fi + ## 0.2.0 < wiretap <=0.2.1 + addenv WIRETAP_INTERFACE_PRIVATEKEY "$PRIV" + addenv WIRETAP_PEER_PUBLICKEY "${PEER}" + addenv WIRETAP_PEER_ENDPOINT "${EP}" + + ## wiretap >=0.3.1 + addenv WIRETAP_RELAY_INTERFACE_PRIVATEKEY "${PRIV}" + addenv WIRETAP_RELAY_PEER_PUBLICKEY "${PEER}" + addenv WIRETAP_RELAY_PEER_ENDPOINT "${EP}" + addenv WIRETAP_SIMPLE "true" if [[ -z $SF_DEBUG ]]; then PATH=".:$PATH" exec -a '[updated]' wiretap serve -q --allowed "${peer_addr}" &>/dev/null & diff --git a/docker-compose.yml b/docker-compose.yml index d72ae29..a21d17b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -157,7 +157,8 @@ services: cap_add: - NET_ADMIN #required environment: - - PRIVATE_KEY=${SF_NORDVPN_PRIVATE_KEY:-} + # - PRIVATE_KEY=${SF_NORDVPN_PRIVATE_KEY:-} + - CONFIG=${SF_NORDVPN_CONFIG:-} - PROVIDER=NordVPN - NETWORK=${SF_NET_LG} - NET_VPN_ROUTER_IP=${SF_NET_VPN_ROUTER_IP} @@ -173,6 +174,7 @@ services: - net.ipv6.conf.all.disable_ipv6=1 - net.ipv4.conf.all.rp_filter=2 - net.ipv4.ip_forward=1 + - net.ipv4.conf.all.src_valid_mark=1 # SNAT - net.netfilter.nf_conntrack_frag6_timeout=10 - net.netfilter.nf_conntrack_generic_timeout=180 # default is 600 - net.netfilter.nf_conntrack_tcp_timeout_syn_sent=10 # default is 120 @@ -222,6 +224,7 @@ services: - net.ipv6.conf.all.disable_ipv6=1 - net.ipv4.conf.all.rp_filter=2 - net.ipv4.ip_forward=1 + - net.ipv4.conf.all.src_valid_mark=1 # SNAT - net.netfilter.nf_conntrack_frag6_timeout=10 - net.netfilter.nf_conntrack_generic_timeout=180 # default is 600 - net.netfilter.nf_conntrack_tcp_timeout_syn_sent=10 # default is 120 @@ -240,6 +243,8 @@ services: - "${SF_SHMDIR:-/dev/shm/sf}/config-for-guest:/config/guest" # vpn_status to guest - "${SF_SHMDIR:-/dev/shm/sf}/run/redis/sock:/redis-sock" - "${SF_BASEDIR:-.}/sfbin:/sf/bin:ro" + # entrypoint: sleep infinity # FIXME-2022 + mullvad: image: hackerschoice/cryptostorm @@ -271,6 +276,7 @@ services: - net.ipv6.conf.all.disable_ipv6=1 - net.ipv4.conf.all.rp_filter=2 - net.ipv4.ip_forward=1 + - net.ipv4.conf.all.src_valid_mark=1 # SNAT - net.netfilter.nf_conntrack_frag6_timeout=10 - net.netfilter.nf_conntrack_generic_timeout=180 # default is 600 - net.netfilter.nf_conntrack_tcp_timeout_syn_sent=10 # default is 120 @@ -696,6 +702,8 @@ networks: guest-net: name: sf-guest driver: bridge + driver_opts: + com.docker.network.driver.mtu: 1420 # Can not use 'internal'. This will only remvoe the host's bridge # but this also means we can not route via 10.11.0.* even if we can # ping the router. diff --git a/encfsd/encfsd.sh b/encfsd/encfsd.sh index cf88e5d..52bb01a 100755 --- a/encfsd/encfsd.sh +++ b/encfsd/encfsd.sh @@ -124,6 +124,7 @@ encfs_mount_server() load_limits() { local lid + local token lid="$1" unset SF_USER_FS_SIZE @@ -134,6 +135,11 @@ load_limits() # First source global [[ -f "/config/etc/sf/sf.conf" ]] && eval "$(grep ^SF_ "/config/etc/sf/sf.conf")" + # Then Token + [[ -f "/config/db/user/lg-${lid}/token" ]] && { + token=$(<"/config/db/user/lg-${lid}/token") + source "/config/db/token/token-${token}.conf" 2>/dev/null + } # Then source user specific limits [[ -f "/config/db/user/lg-${lid}/limits.conf" ]] && eval "$(grep ^SF_ "/config/db/user/lg-${lid}/limits.conf")" } diff --git a/guest/Dockerfile b/guest/Dockerfile index de8f390..fca3add 100644 --- a/guest/Dockerfile +++ b/guest/Dockerfile @@ -420,12 +420,21 @@ RUN /pkg-install.sh GUI apt-get install -y --no-install-recommends \ # && apt-get install -y --no-install-recommends "${pkg[@]}" \ # && rm -f /var/lib/apt/lists/xpra*; }' ### 2023-06: https://github.com/Xpra-org/xpra/issues/3863 +# RUN /pkg-install.sh GUI bash -c '{ : \ +# && wget -O "/usr/share/keyrings/xpra.asc" https://xpra.org/xpra-2023.asc \ +# && wget -O "/etc/apt/sources.list.d/xpra-beta.sources" https://raw.githubusercontent.com/Xpra-org/xpra/master/packaging/repos/bookworm/xpra-beta.sources \ +# && apt-get update \ +# && pkg=("xpra" "xpra-html5") \ +# && { [[ $HOSTTYPE != aarch64 ]] && pkg+=("xpra-x11"); true; `### x86_64 only`; } \ +# && apt-get install -y --no-install-recommends "${pkg[@]}" \ +# && rm -f /var/lib/apt/lists/xpra*; }' +### 2023-07: beta is badly synced +### E: Failed to fetch https://xpra.org/beta/bookworm/main/binary-amd64/Packages.gz File has unexpected size (41831 != 39348). Mirror sync in progress? [IP: 78.129.163.65 443] RUN /pkg-install.sh GUI bash -c '{ : \ && wget -O "/usr/share/keyrings/xpra.asc" https://xpra.org/xpra-2023.asc \ - && wget -O "/etc/apt/sources.list.d/xpra-beta.sources" https://raw.githubusercontent.com/Xpra-org/xpra/master/packaging/repos/bookworm/xpra-beta.sources \ + && wget -O "/etc/apt/sources.list.d/xpra.sources" https://raw.githubusercontent.com/Xpra-org/xpra/master/packaging/repos/bookworm/xpra.sources \ && apt-get update \ && pkg=("xpra" "xpra-html5") \ - && { [[ $HOSTTYPE != aarch64 ]] && pkg+=("xpra-x11"); true; `### x86_64 only`; } \ && apt-get install -y --no-install-recommends "${pkg[@]}" \ && rm -f /var/lib/apt/lists/xpra*; }' ### x86_64 only @@ -433,7 +442,7 @@ RUN /pkg-install.sh GUI bash -c '{ [[ $HOSTTYPE != x86_64 ]] && exit 0; cd /usr/ && curl -sf https://download-installer.cdn.mozilla.net/pub/firefox/releases/108.0.1/linux-x86_64/en-US/firefox-108.0.1.tar.bz2 | tar xfvj - \ && ln -s /usr/lib/firefox/firefox /usr/bin/firefox; }' RUN /pkg-install.sh GUI bash -c '{ true; \ - rm -f /etc/apt/sources.list.d/*.list; \ + rm -f /etc/apt/sources.list.d/*.list /etc/apt/sources.list.d/*.sources; \ apt-get update ; }' RUN /pkg-install.sh HUGE ghbin SagerNet/sing-box 'linux-%arch:x86_64=amd64:aarch64=arm64%.' sing-box \ && /pkg-install.sh HACK bin 'https://api.localxpose.io/api/v2/downloads/loclx-linux-%arch:x86_64=amd64:aarch64=arm64%.zip' loclx \ @@ -712,6 +721,7 @@ RUN /pkg-install.sh NET bin https://github.com/hackerschoice/binary/raw/main/gso && /pkg-install.sh NET ghbin schollz/croc 'Linux-%arch:x86_64=64bit:aarch64=ARM64%.deb' \ && /pkg-install.sh NET ghbin vi/websocat '%arch%.*linux-musl' websocat \ && /pkg-install.sh NET ghbin ViRb3/wgcf 'linux_%arch:x86_64=amd64:aarch64=arm64%$' wgcf \ + && /pkg-install.sh NET ghbin poscat0x04/wgcf-teams '-linux' wgcf-teams \ && /pkg-install.sh NET apt-get install -y --no-install-recommends \ hping3 \ ipcalc ipcalc-ng \ @@ -730,7 +740,16 @@ RUN /pkg-install.sh HUGE npm install -g wscat RUN /pkg-install.sh HUGE bash -c 'mkdir -p /usr/share/wordlists; curl -fsSL https://crackstation.net/files/crackstation-human-only.txt.gz | gunzip >/usr/share/wordlists/crackstation-human-only.txt' RUN /pkg-install.sh LARGE apt-get install -y --no-install-recommends \ bpytop \ - btop + btop \ + ncdu +RUN /pkg-install.sh GUI apt-get install -y --no-install-recommends \ + alsa-utils \ + alsamixergui \ + qasmixer +RUN /pkg-install.sh LARGE apt-get install -y --no-install-recommends \ + php8.2-fpm \ + php8.2-xml +RUN /pkg-install.sh HACK pipx install pwncat-cs RUN sed 's/deb-src.*//' -i /etc/apt/sources.list \ && apt-get autoremove -y \ && apt-get update diff --git a/guest/Makefile b/guest/Makefile index 24e1ee9..857ea4d 100644 --- a/guest/Makefile +++ b/guest/Makefile @@ -1,3 +1,9 @@ -all: Dockerfile - docker build --network host --build-arg SF_PACKAGES="$(SF_PACKAGES)" --build-arg GITHUB_TOKEN="$(GITHUB_TOKEN)" -t sf-guest . +ifndef SF_NET + SF_NET=host +endif + +# expoirt SF_NET=container:sf-net +# export DOCKER_BUILDKIT=0 +all: Dockerfile + docker build --network $(SF_NET) --build-arg SF_PACKAGES="$(SF_PACKAGES)" --build-arg GITHUB_TOKEN="$(GITHUB_TOKEN)" -t sf-guest . diff --git a/guest/fs-root/etc/shellrc b/guest/fs-root/etc/shellrc index 553edbf..a3d9e44 100644 --- a/guest/fs-root/etc/shellrc +++ b/guest/fs-root/etc/shellrc @@ -1,5 +1,8 @@ ### Sourced as the last entry from ~/.zshrc or ~/.bashrc +### Force future 'bash -c' to also load /etc/shellrc +export BASH_ENV="/etc/shellrc" + [[ -n $BASH ]] && export SHELL="/bin/bash" # user on zsh and did `bash` # shellcheck disable=SC1091 source "/sf/bin/funcs.sh" 2>/dev/null @@ -9,6 +12,8 @@ alias lt='ls -Alhrt' alias lss='ls -AlhrS' alias xterm='xterm-dark' alias psg='ps alxwww | grep -i -E' +alias reboot='halt' +alias shutdown='halt' function dmesg { [[ ! -t 1 ]] && { command curl -s sf/dmesg/ -dnocolor=1; return; } @@ -74,6 +79,12 @@ PROXY() echo "${arr[$((RANDOM % n))]}" } +# ASN lookup (Careful, using government's beloved team-cymru) +asn() { + [[ -n $1 ]] && { echo -e "begin\nverbose\n${1}\nend"|netcat whois.cymru.com 43| tail -n +2; return; } + (echo -e 'begin\nverbose';cat -;echo end)|netcat whois.cymru.com 43|tail -n +2 +} + docker(){ echo -e >&2 "${CDB}[${CDY}SF${CDB}] ${CR}Docker aint working.${CN} Try ${CDC}udocker${CN} instead." return 255 @@ -221,7 +232,7 @@ tty -s && [[ -n $TERM ]] && [[ "$TERM" != dumb ]] && { } # After 'alias ls=lsd...' -function lsg { +lsg() { [[ ! -t 1 ]] && { ls -Alh | grep -i -E "$*"; return; } ls -Alh --color=always | grep -i -E "$*" } @@ -252,7 +263,7 @@ function lsg { # Make the Project name visibile in the PS1 prompt [[ -z $VIRTUAL_ENV ]] && VIRTUAL_ENV="${SF_PRJ}" -PATH="${HOME:-/sec/root}/go/bin:/sec/root/.local/bin:/sec/usr/sbin:/sec/usr/bin:/sf/bin:$PATH" +PATH="${HOME:-/sec/root}/go/bin:${HOME:-/sec/root}/.cargo/bin:/sec/root/.local/bin:/sec/usr/sbin:/sec/usr/bin:/sf/bin:$PATH" [[ -d /usr/share/doc/python3-impacket/examples ]] && PATH="${PATH}:/usr/share/doc/python3-impacket/examples" _sf_info_non_perm() @@ -281,3 +292,4 @@ apt-get() SHELLNAME="${SHELL##*/}" [[ -f "${HOME}/.gf/gf-completion.${SHELLNAME}" ]] && source "${HOME}/.gf/gf-completion.${SHELLNAME}" unset SHELLNAME + diff --git a/guest/fs-root/sf/bin/geoip b/guest/fs-root/sf/bin/geoip index 924c1e5..bd9b299 100755 --- a/guest/fs-root/sf/bin/geoip +++ b/guest/fs-root/sf/bin/geoip @@ -6,21 +6,29 @@ ip=$1 db="/sf/share/GeoLite2-City.mmdb" [[ -f "/sf/share/dbip-city-lite.mmdb" ]] && db="/sf/share/dbip-city-lite.mmdb" -res=$(mmdbinspect --db "$db" "$ip") || exit +res=$(mmdbinspect --db "$db" "$ip" 2>/dev/null) || { [[ -z $GEOCOL ]] && exit; } city=$(echo "$res" | jq -r '.[0].Records[0].Record.city.names.en | select(. != null)') country=$(echo "$res" | jq -r '.[0].Records[0].Record.country.names.en | select(. != null)') unset YOUR_GEOIP -if [[ -n $city ]] && [[ -n $country ]]; then - YOUR_GEOIP="${city}/${country}" -elif [[ -n $city ]] || [[ -n $country ]]; then - YOUR_GEOIP="${city}${country}" # Either one but not both +if [[ -z $GEOCOL ]]; then + if [[ -n $city ]] && [[ -n $country ]]; then + YOUR_GEOIP="${city}/${country}" + elif [[ -n $city ]] || [[ -n $country ]]; then + YOUR_GEOIP="${city}${country}" # Either one but not both + fi + + [[ -z $YOUR_GEOIP ]] && { + echo >&2 "NOT FOUND" + exit 255 + } +else + str=${city// /_} + str="${str:----} " + YOUR_GEOIP="${str:0:18}" + str=${country// /_} + str="${str:----} " + YOUR_GEOIP+=" ${str:0:18}" fi -[[ -z $YOUR_GEOIP ]] && { - echo >&2 "NOT FOUND" - exit 255 -} - echo "${YOUR_GEOIP}" - diff --git a/guest/setup.sh b/guest/setup.sh index 937c6db..3879f68 100755 --- a/guest/setup.sh +++ b/guest/setup.sh @@ -113,6 +113,9 @@ mk_hook /usr/share/code/bin code mk_hook /usr/share/code code [[ -f /usr/share/code/bin/code.orig ]] && sed 's/PATH\/code\"/PATH\/code.orig\"/' -i /usr/share/code/bin/code.orig +# Apache needs to enable modules +command -v a2enmod >/dev/null && a2enmod php8.2 + # Output warnings and wait (if there are any) [[ ${#WARNS[@]} -gt 0 ]] && { while [[ $i -lt ${#WARNS[@]} ]]; do diff --git a/host/fs-root/bin/segfaultsh b/host/fs-root/bin/segfaultsh index c7c8da5..8ddd36d 100755 --- a/host/fs-root/bin/segfaultsh +++ b/host/fs-root/bin/segfaultsh @@ -1022,7 +1022,8 @@ fi read -r -n128 -t30 SECRET || err=1 echo -en "${CN}" [[ -n $err ]] && exit 255 - SECRET="${SECRET//[^0-9a-zA-Z]}" + SECRET="${SECRET//[^0-9a-zA-Z-]}" + SECRET="${SECRET##*-}" # Remove host part 'lsd-ABCD...' [[ ${#SECRET} -eq 24 ]] && break [[ "$SECRET" == exit ]] && exit 0 [[ "$SECRET" == new ]] && { unset SECRET; break; } @@ -1031,12 +1032,16 @@ fi } # SECRET and SF_DEBUG are user supplied. # Connect to existing session -if [[ -n $SECRET ]] && [[ ${#SECRET} -eq 24 ]] && [[ ! "${SECRET}" =~ [^a-zA-Z0-9] ]]; then - IS_TRY_EXISTING=1 - SF_SEC="${SECRET}" -else - SF_SEC="$(head -c 1024 /dev/urandom | tr -dc '[:alpha:]' | head -c 24)" + +if [[ -n $SECRET ]]; then + SECRET="${SECRET//[^a-zA-Z0-9-]}" + SECRET="${SECRET##*-}" # Remove host part 'lsd-ABCD...' + [[ ${#SECRET} -eq 24 ]] && { + IS_TRY_EXISTING=1 + SF_SEC="${SECRET}" + } fi +[[ -z $SF_SEC ]] && SF_SEC="$(head -c 1024 /dev/urandom | tr -dc '[:alpha:]' | head -c 24)" [[ -n $SF_IS_WEBSHELL ]] && { # Correct YOUR_IP diff --git a/host/mk_sshd.sh b/host/mk_sshd.sh index 9b4476e..bdf6767 100755 --- a/host/mk_sshd.sh +++ b/host/mk_sshd.sh @@ -1,7 +1,7 @@ #! /bin/bash # Executed inside alpine-gcc context to build patched sshd -# diff -u openssh-9.2p1-orig/ openssh-9.2p1-sf/ +# diff -x '!*.[ch]' -u -r openssh-9.2p1-orig openssh-9.2p1-sf | grep -v ^Only DSTDIR="/src/fs-root/usr/sbin" DSTBIN="${DSTDIR}/sshd" diff --git a/host/sf-sshd.patch b/host/sf-sshd.patch index 004e454..c483ee0 100644 --- a/host/sf-sshd.patch +++ b/host/sf-sshd.patch @@ -1,7 +1,7 @@ -diff -x !*.[ch] -u openssh-9.1p1-orig/channels.c openssh-9.1p1-sf/channels.c ---- openssh-9.1p1-orig/channels.c 2022-10-03 15:51:42 -+++ openssh-9.1p1-sf/channels.c 2023-01-29 21:13:05 -@@ -3510,7 +3510,7 @@ +diff -x '!*.[ch]' -u -r openssh-9.2p1-orig/channels.c openssh-9.2p1-sf/channels.c +--- openssh-9.2p1-orig/channels.c 2023-02-02 12:21:54.000000000 +0000 ++++ openssh-9.2p1-sf/channels.c 2023-08-07 11:02:57.954485279 +0000 +@@ -3639,7 +3639,7 @@ ssh->chanctxt->IPv4or6 = af; } @@ -10,7 +10,7 @@ diff -x !*.[ch] -u openssh-9.1p1-orig/channels.c openssh-9.1p1-sf/channels.c /* * Determine whether or not a port forward listens to loopback, the * specified address or wildcard. On the client, a specified bind -@@ -3548,6 +3548,7 @@ +@@ -3677,6 +3677,7 @@ * address and it was overridden. */ if (*listen_addr != '\0' && @@ -18,9 +18,9 @@ diff -x !*.[ch] -u openssh-9.1p1-orig/channels.c openssh-9.1p1-sf/channels.c strcmp(listen_addr, "0.0.0.0") != 0 && strcmp(listen_addr, "*") != 0) { ssh_packet_send_debug(ssh, -diff -x !*.[ch] -u openssh-9.1p1-orig/serverloop.c openssh-9.1p1-sf/serverloop.c ---- openssh-9.1p1-orig/serverloop.c 2022-10-03 15:51:42 -+++ openssh-9.1p1-sf/serverloop.c 2023-01-29 21:39:06 +diff -x '!*.[ch]' -u -r openssh-9.2p1-orig/serverloop.c openssh-9.2p1-sf/serverloop.c +--- openssh-9.2p1-orig/serverloop.c 2023-02-02 12:21:54.000000000 +0000 ++++ openssh-9.2p1-sf/serverloop.c 2023-08-07 17:38:57.711615443 +0000 @@ -102,6 +102,12 @@ /* requested tunnel forwarding interface(s), shared with session.c */ char *tun_fwd_ifnames = NULL; @@ -34,15 +34,15 @@ diff -x !*.[ch] -u openssh-9.1p1-orig/serverloop.c openssh-9.1p1-sf/serverloop.c /* returns 1 if bind to specified port by specified user is permitted */ static int bind_permitted(int port, uid_t uid) -@@ -380,6 +386,8 @@ - if (sigprocmask(SIG_BLOCK, &bsigset, &osigset) == -1) - error_f("bsigset sigprocmask: %s", strerror(errno)); - collect_children(ssh); +@@ -391,6 +397,8 @@ + /* Clean up sessions, utmp, etc. */ + cleanup_exit(255); + } + if (sf_sigusr1_received != 0) + sf_sshd2ns(); - wait_until_can_do_something(ssh, connection_in, connection_out, - &pfd, &npfd_alloc, &npfd_active, rekey_timeout_ms, &osigset, - &conn_in_ready, &conn_out_ready); + + channel_after_poll(ssh, pfd, npfd_active); + if (conn_in_ready && @@ -637,12 +645,14 @@ if (strcmp(ctype, "session") == 0) { @@ -87,10 +87,10 @@ diff -x !*.[ch] -u openssh-9.1p1-orig/serverloop.c openssh-9.1p1-sf/serverloop.c } if ((resp = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); -diff -x !*.[ch] -u openssh-9.1p1-orig/sshd.c openssh-9.1p1-sf/sshd.c ---- openssh-9.1p1-orig/sshd.c 2022-10-03 15:51:42 -+++ openssh-9.1p1-sf/sshd.c 2023-01-29 21:13:05 -@@ -536,8 +536,71 @@ +diff -x '!*.[ch]' -u -r openssh-9.2p1-orig/sshd.c openssh-9.2p1-sf/sshd.c +--- openssh-9.2p1-orig/sshd.c 2023-02-02 12:21:54.000000000 +0000 ++++ openssh-9.2p1-sf/sshd.c 2023-08-07 17:38:29.479621863 +0000 +@@ -536,6 +536,69 @@ return 0; } } @@ -100,7 +100,7 @@ diff -x !*.[ch] -u openssh-9.1p1-orig/sshd.c openssh-9.1p1-sf/sshd.c +#ifndef SECBIT_KEEP_CAPS +#define SECBIT_KEEP_CAPS (1<<4) +#endif - ++ +int sf_done; +int sf_by_signal; +int sf_sigusr1_received; @@ -108,7 +108,7 @@ diff -x !*.[ch] -u openssh-9.1p1-orig/sshd.c openssh-9.1p1-sf/sshd.c +size_t sf_ports_n; +static char sf_nsnet_name[128]; +static struct ssh *sf_ssh; - static void ++static void +cb_sigusr1(int sig) +{ + debug("SIGUSR1 RECEIVED"); @@ -157,12 +157,10 @@ diff -x !*.[ch] -u openssh-9.1p1-orig/sshd.c openssh-9.1p1-sf/sshd.c + + sf_done = 1; +} -+ -+static void + + static void privsep_postauth(struct ssh *ssh, Authctxt *authctxt) - { - #ifdef DISABLE_FD_PASSING -@@ -576,8 +639,34 @@ +@@ -576,9 +639,35 @@ reseed_prngs(); @@ -171,7 +169,7 @@ diff -x !*.[ch] -u openssh-9.1p1-orig/sshd.c openssh-9.1p1-sf/sshd.c + /* Drop privileges */ do_setusercontext(authctxt->pw); -+ + + // Set the effective CAPS to remove SECUREBITS + cap_t caps = cap_get_proc(); + const cap_value_t cl[] = {CAP_SETPCAP}; @@ -194,6 +192,7 @@ diff -x !*.[ch] -u openssh-9.1p1-orig/sshd.c openssh-9.1p1-sf/sshd.c + snprintf(sf_nsnet_name, sizeof sf_nsnet_name, "/dev/shm/ns-net-%d", getpid()); + sf_ssh = ssh; + signal(SIGUSR1, cb_sigusr1); - ++ skip: /* It is safe now to apply the key state */ + monitor_apply_keystate(ssh, pmonitor); diff --git a/master/cgi-bin/rpc b/master/cgi-bin/rpc index 3227771..474d2c8 100755 --- a/master/cgi-bin/rpc +++ b/master/cgi-bin/rpc @@ -38,10 +38,10 @@ Sanitize() GetFormVars() { - local ifs - ifs=$IFS + local IFS IFS=\& read -r -a arr <<< "${REQUEST_BODY}" + unset IFS local i local str @@ -50,6 +50,7 @@ GetFormVars() ((i++)) key=${str%%=*} [[ ${#key} -le 0 ]] && BAIL "Bad Request" "ERROR: " "Body contains bad variable: '$str'" + key=${key,,} val=${str#*=} [[ ${key} == "nocolor" ]] && unset COLOR @@ -59,16 +60,41 @@ GetFormVars() [[ ${key} == "portsecret" ]] && R_PORTSECRET="${val//[^[:alnum:]]}" [[ ${key} == "exit_private" ]] && R_WT_PRIVATE="${val//[^[:alnum:]+\/]}=" [[ ${key} == "exit_public" ]] && R_WT_PUBLIC="${val//[^[:alnum:]+\/]}=" + [[ ${key} == "privatekey" ]] && key="private" [[ ${key} == "private" ]] && R_WG_PRIVATE="${val//[^[:alnum:]+\/]}=" [[ ${key} == "name" ]] && { val="${val//[^[:alnum:]]}"; R_WT_NAME="${val:0:13}"; } + ### wgOUT + [[ ${key} == "psk" ]] && R_OUT_PSK="${val//[^[:alnum:]+\/]}=" + [[ ${key} == "public" ]] && key="peer" # Alias + [[ ${key} == "publickey" ]] && key="peer" # Alias + [[ ${key} == "peer" ]] && R_OUT_PEER="${val//[^[:alnum:]+\/]}=" + # EndPoint must be IPv4 because not all UPLINK VPN support IPv6 + # EndPoint 1.2.3.4 or 1.2.3.4:51820 + [[ ${key} == "ep" ]] && key="endpoint" # Alias + [[ ${key} == "endpoint" ]] && R_OUT_ENDPOINT="${val//[^[:digit:].:]}" + ### if ADDRESS and if it contains ":" then assume IPv6" + [[ ${key} == "address" ]] && [[ ${val} == *":"* ]] && key="ip6" # Alias + + [[ ${key} == "address" ]] && key="ip4" # Alias + [[ ${key} == "ip" ]] && key="ip4" # Alias + [[ ${key} == "ipv4" ]] && key="ip4" # Alias + [[ ${key} == "ip4" ]] && { + val=${val%%\/*} # Strip /32 + R_OUT_IP4="${val//[^0-9.]}" + } + [[ ${key} == "ipv6" ]] && key="ip6" # Alias + [[ ${key} == "address6" ]] && key="ip6" # Alias + [[ ${key} == "addres6" ]] && key="ip6" # Alias + [[ ${key} == "ip6" ]] && { + val=${val%%\/*} # Strip /128 + R_OUT_IP6="${val//[^0-9a-f:]}" + } [[ ${key} == "dev" ]] && { val="${val//[^[:alnum:]]}" WG_DEV="${val:0:13}" [[ ! "${WG_DEV}" =~ ^wg ]] && WG_DEV="wg${WG_DEV}" } done - - IFS=$ifs } # Load PID of WireGuard container @@ -88,7 +114,7 @@ GenSecret() str=${str//[^[:alnum:]]} str=${str:0:$len} - echo $str + echo "$str" } net_print_example() @@ -97,16 +123,17 @@ net_print_example() name="${1}" echo -en "\ -To connect ${G}${name}${N} use this command on the Exit Node: +To connect ${G}${name}${N} use this command on the LINUX Exit Node: ${C}X='${WT_VER}-${WT_PRIVATE}' X+='-${WG_PUBLIC}' X+='-${WG_EP_HOST}:${WG_PORT}-${WG_IPS}' -X=\"\$X\" bash -c \"\$(curl -fsSL thc.org/sfwg)\"${N} - ---OR--- -${C}X='${WT_VER}-${WT_PRIVATE}' -X+='-${WG_PUBLIC}' -X+='-${WG_EP_HOST}:${WG_PORT}-${WG_IPS}' -X=\"\$X\" bash -c \"\$(wget --no-verbose -O- thc.org/sfwg)\"${N} +DL='curl -fsSL thc.org/sfwg || wget --no-verbose -qO- thc.org/sfwg' +X=\"\$X\" bash -c \"\$(sh -c \"\$DL\")\"${N} +or this command on the WINDOWS Exit Node: +${CY}${F}\$env:X='${WT_VER}-${WT_PRIVATE}' +\$env:X+='-${WG_PUBLIC}' +\$env:X+='-${WG_EP_HOST}:${WG_PORT}-${WG_IPS}' +irm https://thc.org/sfwg.ps1 | iex${N} " } @@ -380,6 +407,48 @@ xrm() return $err } +set_route() +{ + # Add static routes for RPC + # nsenter -t "${PID}" -n ip route add "${SF_PC_IP}/32" dev eth0 # NOT NEEDED: RPC is on same network + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route add "${SF_TOR_IP}" via "${SF_NET_LG_ROUTER_IP}" 2>/dev/null + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route add "${SF_NET_ONION}" via "${SF_NET_LG_ROUTER_IP}" 2>/dev/null + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route add "${SF_DNS}" via "${SF_NET_LG_ROUTER_IP}" 2>/dev/null + [[ -n $SF_MULLVAD_ROUTE ]] && nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route add "${SF_MULLVAD_ROUTE}" via "${SF_NET_LG_ROUTER_IP}" 2>/dev/null + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route del default 2>/dev/null + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route add default dev "${WG_DEV}" + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip -6 route add default dev "${WG_DEV}" + + # Packets to 172.16.0.3 should not be forwarded back to 172.16.0.3 + # Can not use 'sysctl net.ipv4.conf.wgExit.forwarding=1' because /proc is mounted ro + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n iptables -I FORWARD -i "${WG_DEV}" -j DROP + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip6tables -I FORWARD -i "${WG_DEV}" -j DROP +} + +set_normal_route() +{ + # Delete static routes + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route del "${SF_TOR_IP}" via "${SF_NET_LG_ROUTER_IP}" 2>/dev/null + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route del "${SF_NET_ONION}" via "${SF_NET_LG_ROUTER_IP}" 2>/dev/null + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route del "${SF_DNS}" via "${SF_NET_LG_ROUTER_IP}" 2>/dev/null + [[ -n $SF_MULLVAD_ROUTE ]] && nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route del "${SF_MULLVAD_ROUTE}" via "${SF_NET_LG_ROUTER_IP}" 2>/dev/null + + # Should not exist anyway: + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route del default 2>/dev/null + + # WG OUT specific + epip=$(nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route show | grep -F "via ${SF_NET_LG_ROUTER_IP} dev" | grep -v ^default) + epip="${epip%% *}" + epip=${epip//[^0-9.]} + [[ -n $epip ]] && nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route del "${epip}" via "${SF_NET_LG_ROUTER_IP}" 2>/dev/null + + # Restore default routing + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route add default via "${SF_NET_LG_ROUTER_IP}" || { echo "Oops. Could not set default route."; return; } + echo -e "${Y}WARNING${N}: All traffic exits via the DEFAULT ROUTE now." + # Zero the file + :>"${LID_PROMPT_FN}" +} + net_down() { local name @@ -395,13 +464,10 @@ net_down() nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip link delete "wg${name}" 2>/dev/null || return fi echo -e "${G}SUCCESS${N}" - echo -e "Use ${C}curl sf/net/up -d name=${name:-}${N} to connect again." - # Restore default routing - nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route add default via "${SF_NET_LG_ROUTER_IP}" || { echo "Oops. Could not set default route."; return; } - echo -e "${Y}WARNING${N}: All traffic exits via the DEFAULT ROUTE now." - # Empty file - >"${LID_PROMPT_FN}" + + set_normal_route + # Delete WG NAME rm -f "${LID_WGNAME_FN:?}" "${USER_DB_WGNAME_UP_FN:?}" } @@ -444,25 +510,26 @@ cmd_net() exit } +wg_show() +{ + if [[ -z $COLOR ]]; then + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n wg show "${WG_DEV}" + else + # Use 'script' to force color output + script -q -c "nsenter.u1000 --setuid 0 --setgid 0 -t \"${PID}\" -n wg show \"${WG_DEV}\"" /dev/null ] [-d private=] - [-d exit_public=] - [-d exit_private=]${N} -Delete Exit Node : ${C}curl sf/net/del -d name=${N} + [-d exit_public=] + [-d exit_private=]${N} +Delete Exit Node : ${C}curl sf/net/del [-d name=]${N} List Exit Nodes : ${C}curl sf/net/list${N} Show connections : ${C}curl sf/net/show${N} Move port to a different Root Server: @@ -544,50 +611,12 @@ CheckGoodKey() [[ ${#key} -eq 44 ]] && return BAIL "${R}ERROR${N}: Bad Key for ${opt}=" } -# shellcheck disable=2188 # unrecognized redirection (haha. shellsheck you suck) -0<&- # Close STDIN -Sanitize -GetFormVars -[[ -n $COLOR ]] && { - # COLOR is set (to 'always') - Y=$CDY - C=$CDC - R=$CR - G=$CDG - M=$CDM - YY=$CY - W=$CW - N=$CN - F=$CF -} -CheckGoodKey "$R_WG_PRIVATE" "--private" -CheckGoodKey "$R_WT_PRIVATE" "--exit_private" -CheckGoodKey "$R_WT_PUBLIC" "--exit_public" +wg_net_init() +{ + local arr + local IFS -[[ -n $R_WT_PRIVATE ]] && [[ -n $R_WT_PUBLIC ]] && BAIL "${R}ERROR${N}: Set either PRIVATE or PUBLIC but not both." - -# Split into arguments -_IFS=$IFS -IFS=/ read -r -a ARGS <<< "${REQUEST_URI:1}" # Ignore first '/'. Split into arguements. -IFS=$_IFS - -[[ "${FCGI_CMD}" == "dmesg" ]] && { - # dmesg --color=always -f kern --level err,warn -e | tail -n100 - dmesg --color="${COLOR:-never}" -f kern --level err -e | tail -n20 - exit -} - -[[ -n $SF_DEBUG ]] && [[ "${FCGI_CMD}" == "env" ]] && { env; exit; } - -# /net -> Show port assignment -# /net/init -> Assigned port to this LID or create new port. -# /net/up -> Create WireGuard interface -# /net/show -> Show WireGuard peers -# /net/down -# /net/del -# /net/list -[[ "${FCGI_CMD}" == "net" ]] && { # Retrieve (LID CID PID) arr=($(redr GET "ip:${REMOTE_ADDR}")) || BAIL "Bad Value" "Bad Value: " "ret=$?, ${#arr[@]}" [[ ${#arr[@]} -ne 3 ]] && BAIL "Value != 3" "Value != 3: " "${#arr[@]}" @@ -600,10 +629,177 @@ IFS=$_IFS # after a SSC restart. LID_WGNAME_FN="/dev/shm/sf/self-for-guest/lg-${LID}/wgname" USER_DB_WGNAME_UP_FN="/config/db/user/lg-${LID}/wg/name_up" + # USER_DB_WGCLIENT_FN="/config/db/user/lg-${LID}/wg/client" # CID="${arr[1]}" PID="${arr[2]}" + # Split into arguments + IFS=/ read -r -a ARGS <<< "${REQUEST_URI:1}" # Ignore first '/'. Split into arguements. + + # Load CLIENT config + # source "${USER_DB_WGCLIENT_FN}" 2>/dev/null +} + +ERR_wg_help_exit() +{ + echo -e "${R}ERROR${N}: $1" + + cmd_wg_help + exit +} + +# CLIENT +cmd_wg_up() +{ + local epip + local args + local err + local epport + + [[ ${R_OUT_ENDPOINT} != *:* ]] && R_OUT_ENDPOINT+=":51820" + epip="${R_OUT_ENDPOINT%%:*}" + [[ -z "$epip" ]] && unset R_OUT_ENDPOINT + [[ -z $R_OUT_ENDPOINT ]] && ERR_wg_help_exit "No EndPoint found. Please use ${C}-d endpoint=1.2.3.4:51820${N}" + + [[ -n ${R_OUT_PSK} ]] && [[ ${#R_OUT_PSK} -ne 44 ]] && ERR_wg_help_exit "Bad PSK. Please use ${C}-d psk=1234567890abcdef1234567890abcdef1234567890a=${N}" + [[ ${#R_OUT_PEER} -ne 44 ]] && ERR_wg_help_exit "Bad public key. Please use ${C}-d PublicKey=1234567890abcdef1234567890abcdef1234567890a=${N}" + [[ ${#R_WG_PRIVATE} -ne 44 ]] && ERR_wg_help_exit "Bad private key. Please use ${C}-d PrivateKey=1234567890abcdef1234567890abcdef1234567890a=${N}" + + [[ -z $R_OUT_IP4 ]] && [[ -z $R_OUT_IP6 ]] && ERR_wg_help_exit "Bad IP (${R_OUT_IP4:-???},${R_OUT_IP6:-???}) for this peer. Please use ${C}-d ip=1.2.3.4${N} and/or ${C}-d ip6=fd:16::1${N}" + + # Delete any EXIT or OUT + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip link delete group 31337 2>/dev/null + + err=$(nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip link add "${WG_DEV}" type wireguard 2>&1) || BAIL "${R}ERROR${N}: Failed: ip link add '${WG_DEV}' (${err:0:64})." "Failed ${WG_DEV}" ": $err" + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip link set "${WG_DEV}" group 31337 || BAIL "${R}ERROR${N}: ip link set FAILED." + [[ -n $R_OUT_IP4 ]] && { nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip address add dev "${WG_DEV}" "${R_OUT_IP4}" || BAIL "${R}ERROR${N}: Failed to assign IPv4 address '${R_OUT_IP4}'."; } + [[ -n $R_OUT_IP6 ]] && { nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip -6 address add dev "${WG_DEV}" "${R_OUT_IP6}" || BAIL "${R}ERROR${N}: Failed to assign IPv6 address '${R_OUT_IP6}'."; } + + args=() + [[ -n $R_OUT_PSK ]] && { + args+=("preshared-key" "/dev/shm/psk.$$") + echo "$R_OUT_PSK" >"/dev/shm/psk.$$" + } + echo "$R_WG_PRIVATE" >"/dev/shm/private.$$" + err=$(nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n wg set "$WG_DEV" private-key "/dev/shm/private.$$" peer "$R_OUT_PEER" "${args[@]}" endpoint "${R_OUT_ENDPOINT}" persistent-keepalive 25 allowed-ips 0.0.0.0/0,::/0 2>&1) || BAIL "${R}ERROR${N}: Failed: wg set (${err:0:128})" + rm -f "/dev/shm/private.$$" "/dev/shm/psk.$$" + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip link set mtu $((1500 - 80 - 80)) up dev "${WG_DEV}" + + # Route to WG endpoint: + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route add "${epip}" via "${SF_NET_LG_ROUTER_IP}" 2>/dev/null + + set_route + echo "(%F{yellow}EXIT:%B${R_WT_NAME:-$epip}%b%F{%(#.blue.green)})" >"${LID_PROMPT_FN}" + echo -e "${G}SUCCESS${N}" + echo -en "\ +--- +Use ${C}curl sf/wg/down${N} to disconnect. +Use ${C}curl sf/wg/show${N} to check when WireGuard to ${G}${R_OUT_ENDPOINT}${N} has connected. +" + + ### Save config +# echo -e "\ +# IS_WG_CLIENT=1 +# WG_DEV=\"${WG_DEV}\"" >"${USER_DB_WGCLIENT_FN}" + exit +} + +cmd_wg_help() +{ + echo -en "\ +Use ${C}curl sf/wg/up -d endpoint= \\ + -d PublicKey= \\ + -d PrivateKey= \\ + -d Address= \\ + -d Address= \\ + -d psk= \\ ${F}# optional${C} + -d name= ${F}# optional${C}${N} +Use ${C}curl sf/wg/down${N} to disconnect. +Use ${C}curl sf/wg/show${N} to check WireGuard connetion." +} + +# CLIENT +cmd_wg_del() +{ + nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip link delete group 31337 2>/dev/null + # [[ -f "${USER_DB_WGCLIENT_FN}" ]] && rm -f "${USER_DB_WGCLIENT_FN}" + echo -e "${G}SUCCESS${N}" + set_normal_route + exit +} + +cmd_wg_show() +{ + local str + str=$(wg_show) + { [[ -z $str ]] || [[ $str == *"No such device"* ]]; } && { + echo -e "${Y}WARNING${N}: No Exit Node configured." + cmd_wg_help + exit + } + echo "$str" + exit +} + +# shellcheck disable=2188 # unrecognized redirection (haha. shellsheck you suck) +0<&- # Close STDIN +Sanitize +GetFormVars +[[ -n $COLOR ]] && { + # COLOR is set (to 'always') + Y=$CDY + C=$CDC + R=$CR + G=$CDG + B=$CB + M=$CDM + YY=$CY + W=$CW + N=$CN + F=$CF +} + + +[[ "${FCGI_CMD}" == "dmesg" ]] && { + # dmesg --color=always -f kern --level err,warn -e | tail -n100 + dmesg --color="${COLOR:-never}" -f kern --level err -e | tail -n20 + exit +} + +[[ -n $SF_DEBUG ]] && [[ "${FCGI_CMD}" == "env" ]] && { env; exit; } + +wg_net_init + +# /wg/up +# /wg/show +# /wg/del +[[ "${FCGI_CMD}" == "wg" ]] && { + [[ -z $WG_DEV ]] && WG_DEV="wgOut" + + [[ ${ARGS[1]} == 'up' ]] && cmd_wg_up + [[ ${ARGS[1]} == 'del' ]] && cmd_wg_del + [[ ${ARGS[1]} == 'down' ]] && cmd_wg_del + [[ ${ARGS[1]} == 'show' ]] && cmd_wg_show + cmd_wg_help + + exit +} + +# /net -> Show port assignment +# /net/init -> Assigned port to this LID or create new port. +# /net/up -> Create WireGuard interface +# /net/show -> Show WireGuard peers +# /net/down +# /net/del +# /net/list +[[ "${FCGI_CMD}" == "net" ]] && { + CheckGoodKey "$R_WG_PRIVATE" "--private" + CheckGoodKey "$R_WT_PRIVATE" "--exit_private" + CheckGoodKey "$R_WT_PUBLIC" "--exit_public" + + [[ -n $R_WT_PRIVATE ]] && [[ -n $R_WT_PUBLIC ]] && BAIL "${R}ERROR${N}: Set either PRIVATE or PUBLIC but not both." + # Sanitize 0.4.8rc1 bug where '172...' was '"172...' in .env WG_IPS="${WG_IPS//[^a-fx0-9\/,:.]}" [[ -z $WG_IPS ]] && WG_IPS="172.16.0.x/16,fd:16::x/104" @@ -678,9 +874,9 @@ IFS=$_IFS err=$(nsenter -t "${WG_PID}" -n ip link add "${WG_DEV}" type wireguard 2>&1) || BAIL "${R}ERROR${N}: Failed: ip link add ${WG_DEV} (${err:0:32})." "Failed ${WG_DEV}" ": $err" nsenter -t "${WG_PID}" -n ip link set "${WG_DEV}" group 31337 || BAIL "${R}ERROR${N}: ip link set FAILED." - echo "$WG_PRIVATE" >/dev/shm/private.$$ + echo "$WG_PRIVATE" >"/dev/shm/private.$$" err=$(nsenter -t "${WG_PID}" -n wg set "${WG_DEV}" listen-port "${WG_PORT}" private-key "/dev/shm/private.$$" peer "${WT_PUBLIC}" allowed-ips 0.0.0.0/0,::/0 2>&1) || BAIL "${R}ERROR${N}: Failed: wg set (${err:0:128})" - rm -f /dev/shm/private.$$ + rm -f "/dev/shm/private.$$" # Move Interface to user's container: err=$(nsenter -t "${WG_PID}" -n ip link set "${WG_DEV}" netns "${PID}" 2>&1) || BAIL "${R}ERROR${N}: Failed to move ${WG_DEV}." "Failed ${WG_DEV} netns $PID" ": $err" @@ -689,20 +885,7 @@ IFS=$_IFS err=$(nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip -6 address add "${WG_IP6}" dev "${WG_DEV}" 2>&1) || echo >&2 "${CR}ERROR${CN}: ip -6: $err" nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip link set mtu 1420 up dev "${WG_DEV}" - # Add static routes for RPC - # nsenter -t "${PID}" -n ip route add "${SF_PC_IP}/32" dev eth0 # NOT NEEDED: RPC is on same network - nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route add "${SF_TOR_IP}" via "${SF_NET_LG_ROUTER_IP}" 2>/dev/null - nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route add "${SF_NET_ONION}" via "${SF_NET_LG_ROUTER_IP}" 2>/dev/null - nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route add "${SF_DNS}" via "${SF_NET_LG_ROUTER_IP}" 2>/dev/null - [[ -n $SF_MULLVAD_ROUTE ]] && nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route add "${SF_MULLVAD_ROUTE}" via "${SF_NET_LG_ROUTER_IP}" 2>/dev/null - nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route del default 2>/dev/null - nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip route add default dev "${WG_DEV}" - nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip -6 route add default dev "${WG_DEV}" - - # Packets to 172.16.0.3 should not be forwarded back to 172.16.0.3 - # Can not use 'sysctl net.ipv4.conf.wgExit.forwarding=1' because /proc is mounted ro - nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n iptables -I FORWARD -i "${WG_DEV}" -j DROP - nsenter.u1000 --setuid 0 --setgid 0 -t "${PID}" -n ip6tables -I FORWARD -i "${WG_DEV}" -j DROP + set_route echo "${WT_NAME}" >"${LID_WGNAME_FN}" echo "${WT_NAME}" >"${USER_DB_WGNAME_UP_FN}" diff --git a/provision/env.example b/provision/env.example index ee563b3..27af7f9 100644 --- a/provision/env.example +++ b/provision/env.example @@ -9,13 +9,17 @@ SF_BASEDIR=${HOME}/segfault #SF_USER=root #SF_USER_PASSWORD=segfault #SF_FQDN=CHANGEME.segfault-net +#SF_IP=1.2.3.4 ## Route TOR VIA VPN (the default it to route directly to Internet) #SF_TOR_VIA_VPN= ## Use no VPN at all and route directly to the Internet. #SF_DIRECT= +#### NordVPN #### ## Obtain the private key by executing: ## docker run --rm --cap-add=NET_ADMIN -e USER=XXX -e PASS=YYY bubuntux/nordvpn:get_private_key -#SF_NORDVPN_PRIVATE_KEY= +## Create a Country <> ID list for NordVPN: +## curl --silent "https://api.nordvpn.com/v1/servers/countries" | jq --raw-output '.[] | [.id, .name] | @tsv' +#SF_NORDVPN_CONFIG=filters\[country_id\]=81::::::none:::none ## Obtain the config by executing: ## docker run --rm --e CRYPTOSTORM_TOKEN=XXX --entrypoint /getkey.sh hackerschoice/cryptostorm ## Example: cs-tokyo+cs-sydney:::::::::
diff --git a/provision/init-linux.sh b/provision/init-linux.sh index 8c1eafc..fc1da59 100755 --- a/provision/init-linux.sh +++ b/provision/init-linux.sh @@ -169,7 +169,7 @@ init_config_run() [[ ! "$SFI_SRCDIR" -ef "$SF_BASEDIR" ]] && [[ -d "${SF_BASEDIR}/sfbin" ]] && rm -rf "${SF_BASEDIR}/sfbin" mergedir "sfbin" - grep -F .bashrc /root/.bashrc >/dev/null || echo ". .bashrc" >>/root/.bash_profile + grep -F .bashrc /root/.bash_profile >/dev/null || echo ". .bashrc" >>/root/.bash_profile grep -F funcs_admin.sh /root/.bash_profile >/dev/null || echo ". ${SF_BASEDIR}/sfbin/funcs_admin.sh" >>/root/.bash_profile # Configure BFQ module grep ^bfq /etc/modules &>/dev/null || echo "bfq" >>/etc/modules @@ -278,6 +278,9 @@ fi journalctl --vacuum-size=20M journalctl --vacuum-time=10d +sed 's/rotate 4/rotate 2/' -i /etc/logrotate.conf +sed 's/rotate 4/rotate 2\n\tsize 64M\n\tminsize 128k/' -i /etc/logrotate.d/rsyslog + # NOTE: Only needed if source is mounted into vmbox (for testing) [[ "$(stat -c %G /research/segfault 2>/dev/null)" == "vboxsf" ]] && usermod -a -G vboxsf "${SF_HOST_USER}" diff --git a/router/init.sh b/router/init.sh index fd882ee..cf7d40f 100755 --- a/router/init.sh +++ b/router/init.sh @@ -154,14 +154,14 @@ use_vpn() # iproute2 does not support nexthop-multipath and fwmark tables. # ip route add default nexthop via 172.20.0.253 nexthop via 172.20.0.252 table 53 # Error: "nexthop" or end of line is expected instead of "table" - # Instead use the first for port 53 traffic. - # ip route add default via "${gw_dns_ip[0]}" table 53 + # Instead use our own fwmark by dns-tranction-id to spread port 53 load i=0 for n in 0 1 2 3; do ip route add default via "${gw_dns_ip[$i]}" table "${n}53" ((i++)) [[ $i -ge ${#gw_dns_ip[@]} ]] && i=0 done + # Previously we routed just via first gw: ip route add default via "${gw_dns_ip[0]}" table 53 } ip route add default "${gw[@]}" } @@ -329,6 +329,7 @@ ipt_direct() ipset_add_domain 8lgm.segfault.net ipset_add_domain adm.segfault.net ipset_add_domain beta.segfault.net + ipset_add_domain lulz.segfault.net # GitHub ipset_add_domain github.com diff --git a/sfbin/funcs_admin.sh b/sfbin/funcs_admin.sh index 17d5dcf..52c0b4d 100644 --- a/sfbin/funcs_admin.sh +++ b/sfbin/funcs_admin.sh @@ -656,6 +656,35 @@ docker_clean() echo "May want to ${CDC}docker system prune -f -a${CN}" } +# Convert a PID to a LG +pid2lg() +{ + local p c str + p=$1 + c=$(grep docker- "/proc/${p}/cgroup") + [[ -z $c ]] && { echo "LG-NOT-FOUND"; return 255; } + c=${c##*docker-} + c=${c%\.scope} + str=$(docker inspect "$c" -f '{{.Name}}') + basename "$str" +} + +# grep through all environ of first child of sshd +lgenv() +{ + local x y p match + for x in /proc/*/exe; do + [[ $(readlink "$x") != "/usr/sbin/sshd" ]] && continue + p=$(dirname "$x") + p=${p##*\/} + for y in $(<"/proc/${p}/task/${p}/children"); do + strings "/proc/${y}/environ" | grep "$@" || continue + echo "$y $(pid2lg "$y") $(strings /proc/${y}/environ| grep SSH_CONNECTION)" + break + done + done +} + # [Sort Row] _sfmax() { diff --git a/sfbin/sf b/sfbin/sf index b867a3e..6072e33 100755 --- a/sfbin/sf +++ b/sfbin/sf @@ -134,6 +134,23 @@ warn_file() WARN "Not found: $1" } +warn_outdated() +{ + local fn dst src + dst="${SF_BASEDIR}/${1}" + src="${BINDIR}/../${1}" + + [[ ! -f "$dst" ]] && { WARN "Not found: $dst"; return; } + [[ ! -f "$src" ]] && ERREXIT 255 "Not found: $src" + + # Installed file $dst is newer or equal than $src + [[ ! "$dst" -ot "$src" ]] && return + + [[ $(stat -c%s "$dst") -eq $(stat -c%s "$src") ]] && return + + WARN "$dst is outdated? Try ${CDC}touch $dst${CN} to ignore." +} + load_env [[ -z $SF_DATADIR ]] && SF_DATADIR="${SF_BASEDIR}/data" [[ -z $SF_SHMDIR ]] && SF_SHMDIR="/dev/shm/sf" @@ -202,6 +219,8 @@ blockio_init sysinc net.ipv4.neigh.default.gc_thresh3 65536 sysinc net.netfilter.nf_conntrack_buckets 16384 # default is 65536 for >4GB systems sysinc net.netfilter.nf_conntrack_max 1048576 +# find /proc/*/fd -lname anon_inode:inotify | cut -d/ -f3 | xargs -I '{}' -- ps --no-headers -o '%p %U %c' -p '{}' | uniq -c | sort -nr +sysinc fs.inotify.max_user_instances 1024 # Conntrack & Namespaces is a mess. Restricting these inside a container # only results that the connection is dropped sooner but the state still @@ -225,9 +244,11 @@ sysdec net.netfilter.nf_conntrack_udp_timeout 10 # default is 30 # 8192 => 16g as HUGE [[ ! $(cat /proc/sys/vm/nr_hugepages) -gt 0 ]] && WARN "Huge Tables not set. Consider ${CDC}echo \"vm.nr_hugepages=8192\" >>/etc/sysctl.conf && sysctl -w vm.nr_hugepages=8192${CN}" -warn_file "${SF_BASEDIR}/config/etc/nginx/nginx-rpc.conf" -warn_file "${SF_BASEDIR}/config/etc/nginx/nginx.conf" -warn_file "${SF_BASEDIR}/config/etc/sf/sf.conf" +# Warn for outdated files in /sf/config/* (that are older and different size) +mapfile -t arr < <(cd "${BINDIR}/../" || exit; find config -type f) +for fn in "${arr[@]}"; do + warn_outdated "$fn" +done # Check if there are any fils in /sf/sfbin that are not equal to ./sfbin for x in "${BINDIR}/"*; do