mirror of
https://github.com/hackerschoice/segfault.git
synced 2024-06-28 09:41:18 +00:00
242 lines
6.0 KiB
Bash
Executable File
242 lines
6.0 KiB
Bash
Executable File
#! /bin/bash
|
|
|
|
# CONTEXT: VPN context. Call from portd.sh (sf-portd context)
|
|
|
|
# Executed by portd.sh inside VPN context.
|
|
# Set the FW and routing for reverse ip port forwarding.
|
|
|
|
source "/sf/bin/funcs.sh"
|
|
source "/sf/bin/funcs_redis.sh"
|
|
|
|
ipbydev()
|
|
{
|
|
local _ip
|
|
_ip="$(ip addr show "${1}")"
|
|
_ip="${_ip#*inet }"
|
|
_ip="${_ip%%/*}"
|
|
[[ -n $_ip ]] && { echo "$_ip"; return; }
|
|
echo -e >&2 "IP for dev '${1}' not found. Using $2"
|
|
echo "${2:?}"
|
|
}
|
|
|
|
# Remove a single iptable line and associated forward rules.
|
|
# ["output of iptables -L -n"] as a single string.
|
|
fw_del_single()
|
|
{
|
|
local line
|
|
local c_ip
|
|
local port
|
|
line="$1"
|
|
|
|
a=($line)
|
|
c_ip="${a[7]##*:}"
|
|
port="${a[6]##*:}"
|
|
iptables -t nat -D PREROUTING -i wg0 -p "${a[5]}" -d "${a[4]}" --dport "${port}" -j DNAT --to-destination "${c_ip}"
|
|
iptables -D FORWARD -i wg0 -p "${a[5]}" -d "${c_ip}" --dport "${port}" -j ACCEPT
|
|
}
|
|
|
|
# Delete all Port Forwarding rules matching this R-PORT
|
|
# [R-PORT]
|
|
fw_del()
|
|
{
|
|
local port
|
|
port="$1"
|
|
|
|
local line
|
|
iptables -t nat -L PREROUTING -n | grep -F "dpt:${port}" | while read line; do
|
|
fw_del_single "$line"
|
|
done
|
|
|
|
return
|
|
}
|
|
|
|
# [IP] - String matches such as "10.11." or "10.11.0.8"] are permitted.
|
|
fw_del_byip()
|
|
{
|
|
local match
|
|
match="$1"
|
|
|
|
iptables -t nat -L PREROUTING -n | while read x; do
|
|
[[ "${a[4]}" != "${match}"* ]] && continue
|
|
del_single "$x"
|
|
done
|
|
|
|
return
|
|
}
|
|
|
|
# Remove the Port Forward & FW rules for a list of ports.
|
|
# Called from portd.sh when a container exited (by sf-destructor)
|
|
#
|
|
# [<IPPORT>...]
|
|
cmd_delipports()
|
|
{
|
|
local ipport
|
|
local r_port
|
|
local res
|
|
local err
|
|
|
|
[[ "${PROVIDER,,}" != "cryptostorm" ]] && return
|
|
|
|
DEBUGF "cmd_delipports ${PROVIDER} '${*}'"
|
|
|
|
err=1
|
|
for ipport in "$@"; do
|
|
r_port="${ipport##*:}"
|
|
res=$(curl -fsSL --retry 3 --max-time 10 http://10.31.33.7/fwd "-ddelfwd=${r_port}" 2>/dev/null) && {
|
|
[[ $res == *"has been removed"* ]] && unset err
|
|
}
|
|
|
|
[[ -n $err ]] && {
|
|
ERR "${PROVIDER} Failed to remove Port Forward (${ipport})"
|
|
echo "------------------------"
|
|
echo "${res:0:1024}"
|
|
echo "------------------------"
|
|
}
|
|
|
|
fw_del "${r_port}"
|
|
done
|
|
}
|
|
|
|
# Add firewall/routing information for this port.
|
|
#
|
|
# [R-IP] [PORT] [CONTAINER-IP] [LID]
|
|
cmd_fwport()
|
|
{
|
|
local port
|
|
local r_ip
|
|
local c_ip
|
|
local wg_ip
|
|
local lid
|
|
r_ip="$1"
|
|
port="$2"
|
|
c_ip="$3"
|
|
lid="$4"
|
|
|
|
[[ -z $c_ip || -z $port ]] && { echo "Bad IP:PORT. ip='${c_ip}' port='$port'"; return 255; }
|
|
fw_del "${port}"
|
|
|
|
wg_ip=$(ipbydev wg0 "")
|
|
[[ -z $wg_ip ]] && { echo "Could not retrieve my own wg0 address."; return 255; }
|
|
|
|
for proto in tcp udp; do
|
|
iptables -t nat -A PREROUTING -i wg0 -p ${proto} -d "${wg_ip}" --dport "${port}" -j DNAT --to-destination "${c_ip}" || break
|
|
iptables -A FORWARD -i wg0 -p ${proto} -d "${c_ip}" --dport "${port}" -j ACCEPT || break
|
|
done
|
|
[[ $? -ne 0 ]] && { echo "iptables failed with $?."; return 255; }
|
|
|
|
LOG "${lid}" "Forwarding ${r_ip}:${port} -> ${c_ip}:${port}"
|
|
return 0
|
|
}
|
|
|
|
# Delete stale ports
|
|
# This can happen if there was a timeout to reach the VPN provider.
|
|
# Check through all ports and compare to assigned ports in ReDis
|
|
# Testing: delstale_cs "$(curl -fsSL --retry 3 --max-time 10 http://10.31.33.7/fwd)"
|
|
# [res] [port]
|
|
# + +---- The last port that got added (and not yet added to portd:ports and thus must be ignored)
|
|
# +----------- The result from curl -dport=asdf output
|
|
delstale_cs()
|
|
{
|
|
local res
|
|
local IFS_old
|
|
local arr
|
|
local rarr
|
|
local r
|
|
local str
|
|
local skip_port
|
|
res="$1"
|
|
skip_port="$2"
|
|
IFS_old="$IFS"
|
|
|
|
IFS=$'\n'
|
|
|
|
# Assigned to containers
|
|
rarr=($(redr SMEMBERS "portd:assigned-CryptoStorm"))
|
|
for str in "${rarr[@]}"; do
|
|
r+=("${str##* }")
|
|
done
|
|
|
|
# Assigned in pool of available ports
|
|
rarr=($(redr SMEMBERS "portd:ports"))
|
|
for str in "${rarr[@]}"; do
|
|
[[ "${str%% *}" != "CryptoStorm" ]] && continue
|
|
r+=("${str##* }")
|
|
done
|
|
|
|
# Check if CS's return of forwarded port are all
|
|
# still in our list "r" and delete from CS if they are not.
|
|
arr=($res)
|
|
for str in "${arr[@]}"; do
|
|
[[ "$str" != *" ->"* ]] && continue
|
|
ipport="${str%% *}"
|
|
[[ ${r[*]} == *"$ipport"* ]] && continue
|
|
port=${ipport##*:}
|
|
[[ "$port" == "$skip_port" ]] && continue
|
|
WARN "${PROVIDER}: Removing STALE ${ipport}"
|
|
[[ "$port" =~ [^0-9] ]] && continue
|
|
curl -fsSL --max-time 5 http://10.31.33.7/fwd -ddelfwd="${port}" >/dev/null
|
|
done
|
|
|
|
IFS="$IFS_old"
|
|
}
|
|
|
|
# Try to request [NUMBER] more ports from the provider.
|
|
# Return ="[PROVIDER] ip:ports"= (with quotes) to STDOUT and 0 if
|
|
# any port was successfully requested.
|
|
#
|
|
# Return 255 if this provider should never be tried again.
|
|
# Return 0 on success.
|
|
#
|
|
# [NUMBER]
|
|
cmd_moreports()
|
|
{
|
|
local members
|
|
local members_num
|
|
local req_num
|
|
local err
|
|
err=200
|
|
req_num="$1"
|
|
|
|
|
|
[[ "${PROVIDER,,}" != "cryptostorm" ]] && return 255
|
|
|
|
local i
|
|
i=0
|
|
members_num=0
|
|
# Try 5x the number requested in case we accidentally request a port
|
|
# that was already requested (by us or somebody else).
|
|
while [[ $i -lt $((req_num * 5)) ]]; do
|
|
port=$((30000 + RANDOM % 35534))
|
|
res=$(curl -fsSL --retry 3 --max-time 10 http://10.31.33.7/fwd -dport="$port") || break
|
|
# Check and delete and stale ports
|
|
[[ $i -eq 0 ]] && delstale_cs "$res" "$port" >/dev/null
|
|
((i++))
|
|
# You already have 100 forwards. The max is 100. Please delete some of the existing ones first.
|
|
[[ "$res" == *"You already have "* ]] && { ERR "${PROVIDER} Out of ports!!!"; err=255; break; } # Max Port Forward reached.
|
|
[[ "$res" != *"is now forwarding"* ]] && { WARN "${PROVIDER} Failed to get port=${port}."; continue; } # Failed. Try again.
|
|
|
|
res="${res%% is now forwarding*}"
|
|
ip="${res##* }"
|
|
# Must sanitize
|
|
[[ "$ip" =~ [^0-9.] ]] && break
|
|
members+="${PROVIDER} ${ip}:${port}"$'\n'
|
|
((members_num++))
|
|
|
|
[[ $members_num -ge $req_num ]] && break
|
|
done
|
|
|
|
# Could be a temporary failure of curl (200) or fatal (255, out of ports)
|
|
[[ $members_num -le 0 ]] && return "$err"
|
|
|
|
echo "${members[*]}"
|
|
return 0
|
|
}
|
|
|
|
cmd="$1"
|
|
shift 1
|
|
|
|
[[ "$cmd" == fwport ]] && { cmd_fwport "$@"; exit; }
|
|
[[ "$cmd" == moreports ]] && { cmd_moreports "$@"; exit; }
|
|
[[ "$cmd" == delipports ]] && { cmd_delipports "$@"; exit; } # [<IPPORT> ...]
|
|
[[ "$cmd" == fw_delall ]] && { fw_del_byip "10.11."; exit; }
|