bypasser-shell/bypasser
2025-09-17 10:06:29 -06:00

462 lines
9.9 KiB
Bash
Executable file

#!/bin/sh
BP_SYSCTL="${SYSCTL_CONF_FILE:-/etc/sysctl.d/bypasser-forwarding.conf}"
BP_WG_INTERFACE_PREFIX="bp-"
BP_WG_DIR="${BP_WG_DIR:-/etc/wireguard}"
BP_WG_PEERS_DIR="$BP_WG_DIR"/peers
BP_WG_DEFAULT_MIN_PORT="${BP_WG_DEFAULT_MIN_PORT:-55107}"
BP_WG_DEFAULT_MAX_PORT="${BP_WG_DEFAULT_MAX_PORT:-55207}"
BG_WG_SUBNET_PREFIX="69.0"
BG_WG_INTERFACE_SUBNET_MASK="24"
BG_WG_PEER_SUBNET_MASK="32"
_IPV4_RULE="net.ipv4.ip_forward"
_IPV6_RULE="net.ipv6.conf.all.forwarding"
OPT_TARGET="$1"
OPT_ACTION="$2"
OPT_ARG="$3"
if [ "$(whoami)" != "root" ]; then
echo "Error, must run as root"
exit 1
fi
_print_help() {
echo "Usage:"
echo " bypasser [vpn|peer] [<vpn_name>|<vpn_name>:<peer_name>]"
echo
echo "Examples:"
echo
echo "Add a new VPN:"
echo " bypasser vpn new myvpn"
echo
echo "Add a new peer:"
echo " bypasser peer new myvpn:mypeer"
}
_get_vpn_name() {
printf "Enter a name for the new virtual network"
read -r _name
if [ -z $_name ]; then
return 1
fi
echo "$_name"
}
_vpn_name_available() {
_vpn_name="$1"
[ -z $_vpn_name ] && return 1
_vpn_file="$BP_WG_DIR"/"$BP_WG_INTERFACE_PREFIX$_vpn_name".conf
! [ -f "$_vpn_file" ]
}
_enable_forwarding() {
printf "%s = 1\n%s = 1" "$_IPV4_RULE" "$_IPV6_RULE" >"$BP_SYSCTL"
sysctl -p >/dev/null 2>&1
sysctl --system >/dev/null 2>&1
}
_check_forwarding() {
_v4="$(sysctl "$_IPV4_RULE")"
_v4="${_v4##*= }"
_v6="$(sysctl "$_IPV6_RULE")"
_v6="${_v6##*= }"
if [ "$_v4" = 0 ] || [ "$_v6" = 0 ]; then
return 1
fi
}
_vpn_list() {
echo "Available VPNs in '$BP_WG_DIR':"
if ! [ -d "$BP_WG_DIR" ] || [ -z "$BP_WG_DIR" ]; then
return 0
fi
for f in "$BP_WG_DIR"/*; do
if [ -f "$f" ]; then
vpn="${f##*/}"
vpn="${vpn#${BP_WG_INTERFACE_PREFIX}}"
vpn="${vpn%.conf}"
echo " - $vpn"
fi
done
}
_peer_list() {
echo "Available Peers in '$BP_WG_PEERS_DIR':"
if ! [ -d "$BP_WG_PEERS_DIR" ] || [ -z "$BP_WG_PEERS_DIR" ]; then
return 0
fi
for f in "$BP_WG_PEERS_DIR"/*; do
if [ -f "$f" ]; then
peer="${f##*/}"
peer="${peer#${BP_WG_INTERFACE_PREFIX}}"
peer="${peer%.conf}"
peer="${peer%.conf}"
vpn="${peer%%-*}"
peer="${peer##*-}"
echo " - $vpn:$peer"
fi
done
}
_vpn_restart() {
_vpn_name="$1"
_vpn_interface="$BP_WG_INTERFACE_PREFIX$_vpn_name"
wg-quick down "$_vpn_interface"
systemctl restart wg-quick@"$_vpn_interface"
}
_vpn_enable() {
_vpn_name="$1"
_vpn_interface="$BP_WG_INTERFACE_PREFIX$_vpn_name"
wg-quick down "$_vpn_interface"
systemctl enable --now wg-quick@"$_vpn_interface"
}
_vpn_disable() {
_vpn_name="$1"
_vpn_interface="$BP_WG_INTERFACE_PREFIX$_vpn_name"
wg-quick down "$_vpn_interface"
systemctl disable --now wg-quick@"$_vpn_interface"
}
_get_available_port() {
_avail_port="$((BP_WG_DEFAULT_MIN_PORT - 1))"
for f in "$BP_WG_DIR"/*; do
if [ -f "$f" ]; then
while read -r line; do
case "$line" in
*ListenPort*)
_port="${line##* = }"
if [ -n "$_port" ] && [ "$_port" -gt "$_avail_port" ]; then
_avail_port="$_port"
fi
;;
esac
done <"$f"
fi
done
echo "$((_avail_port + 1))"
}
_vpn_new() {
if ! [ -d "$BP_WG_DIR" ] || [ -z "$BP_WG_DIR" ]; then
echo "Error: directory '$BP_WG_DIR' nonexistent, create it (and set 600 permissions) to add new VPNs"
return 1
fi
_vpn_name="$1"
_vpn_file="$BP_WG_DIR"/"$BP_WG_INTERFACE_PREFIX$_vpn_name".conf
if [ -f "$_vpn_file" ]; then
echo "Error: vpn name '$_vpn_name' already exists in '$_vpn_file'"
return 1
fi
_port="$(_get_available_port)"
if [ "$?" != 0 ] || [ -z "$_port" ]; then
echo "Error: could not get an available port"
return 1
fi
_server_sec_key=$(wg genkey)
if [ "$?" != 0 ]; then
echo "Error: could not generate private key"
return 1
fi
_highest="$(_highest_interface)"
_new=$((_highest + 1))
echo "[Interface]
PrivateKey = ${_server_sec_key}
ListenPort = ${_port}
Address = ${BG_WG_SUBNET_PREFIX}.${_new}.1/${BG_WG_INTERFACE_SUBNET_MASK}" >"$_vpn_file"
chmod 600 "$_vpn_file"
_vpn_enable "$_vpn_name"
}
_vpn_rm() {
if ! [ -d "$BP_WG_DIR" ] || [ -z "$BP_WG_DIR" ]; then
return 1
fi
_vpn_name="$1"
_vpn_file="$BP_WG_DIR"/"$BP_WG_INTERFACE_PREFIX$_vpn_name".conf
_vpn_disable "$_vpn_name"
if [ -f "$_vpn_file" ]; then
sudo rm -f "$_vpn_file"
else
echo "Error: file '$_vpn_file' nonexistent"
return 1
fi
}
_peer_rm() {
if ! [ -d "$BP_WG_PEERS_DIR" ] || [ -z "$BP_WG_PEERS_DIR" ]; then
return 1
fi
_peer_name="$1"
_vpn_name="${_peer_name%%:*}"
_peer_name="${_peer_name##*:}"
_peer_file="$BP_WG_PEERS_DIR"/"$BP_WG_INTERFACE_PREFIX$_vpn_name-$_peer_name".conf
if ! [ -f "$_peer_file" ]; then
echo "Error: peer file '$_peer_file' nonexistent"
return 1
fi
if [ -f "$_peer_file" ]; then
sudo rm -f "$_peer_file"
else
echo "Error: file '$_peer_file' nonexistent"
return 1
fi
_vpn_restart "$_vpn_name"
}
_get_host_addr() {
_addr="$1"
_addr="${_addr%%/*}"
_host="${_addr#${BG_WG_SUBNET_PREFIX}.}"
echo "$_host"
}
_get_interface_octet() {
_host="$(_get_host_addr "$1")"
echo "${_host%.*}"
}
_get_peer_octet() {
_host="$(_get_host_addr "$1")"
echo "${_host#*.}"
}
_highest_interface() {
_highest=0
for f in "$BP_WG_DIR"/*; do
if [ -f "$f" ]; then
while read -r line; do
case "$line" in
*Address*)
_addr="${line##* = }"
_interface_octet="$(_get_interface_octet "$_addr")"
if [ -n "$_interface_octet" ] && [ "$_interface_octet" -gt "$_highest" ]; then
_highest="$_interface_octet"
fi
;;
esac
done <"$f"
fi
done
echo "$_highest"
}
_highest_peer_in_vpn() {
_highest=1
_interface_conf="$BP_WG_DIR"/"$BP_WG_INTERFACE_PREFIX$1".conf
if [ -f "$_interface_conf" ]; then
while read -r line; do
case "$line" in
*AllowedIPs*)
_addr="${line##* = }"
_peer_octet="$(_get_peer_octet "$_addr")"
if [ -n "$_peer_octet" ] && [ "$_peer_octet" -gt "$_highest" ]; then
_highest="$_peer_octet"
fi
;;
esac
done <"$_interface_conf"
fi
echo "$_highest"
}
_vpn_exists() {
[ -f "$BP_WG_DIR"/"$1" ]
}
_get_interface_address() {
_interface_file="$BP_WG_DIR"/"$BP_WG_INTERFACE_PREFIX$1".conf
if [ -f "$_interface_file" ]; then
while read -r line; do
case "$line" in
*Address*)
_addr="${line##* = }"
echo "$(_get_interface_octet "$_addr")"
break
;;
esac
done <"$_interface_file"
else
return 1
fi
}
_peer_new() {
_arg="$1"
if ! [ -d "$BP_WG_DIR" ] || [ -z "$BP_WG_DIR" ]; then
echo "Error: directory '$BP_WG_DIR' nonexistent, create it (and set 600 permissions) to add new VPNs"
return 1
fi
if ! [ -d "$BP_WG_PEERS_DIR" ] || [ -z "$BP_WG_PEERS_DIR" ]; then
echo "Error: directory '$BP_WG_PEERS_DIR' nonexistent, create it (and set 600 permissions) to add new VPNs"
return 1
fi
_vpn_name="${_arg%%:*}"
_peer_name="${_arg##*:}"
_vpn_file="$BP_WG_DIR"/"$BP_WG_INTERFACE_PREFIX$_vpn_name".conf
_peer_file="$BP_WG_PEERS_DIR"/"$BP_WG_INTERFACE_PREFIX$_vpn_name"-"$_peer_name".conf
if [ -z "$_vpn_name" ] || [ -z "$_peer_name" ]; then
echo "Error: invalid vpn or peer name"
return 1
fi
if [ -f "$_peer_file" ]; then
echo "Error: peer file '$_peer_file' already exists"
return 1
fi
_server_sec_key=
while read -r line; do
case "$line" in
*PrivateKey*)
_server_sec_key="${line##* = }"
break
;;
esac
done <"$_vpn_file"
if [ -z "$_server_sec_key" ]; then
echo "Error: could not find interface private key"
return 1
fi
_server_pub_key=$(echo "${_server_sec_key}" | wg pubkey)
_server_port=
while read -r line; do
case "$line" in
*ListenPort*)
_server_port="${line##* = }"
break
;;
esac
done <"$_vpn_file"
if [ -z "$_server_port" ]; then
echo "Error: could not find interface ListenPort"
return 1
fi
_highest="$(_highest_peer_in_vpn "$_vpn_name")"
_new_octet=$((_highest + 1))
_addr="$(_get_interface_address "$_vpn_name")"
_vpn_octet="$(_get_interface_octet "$_addr")"
if [ -z "$_vpn_octet" ]; then
echo "Error: invalid vpn name"
return 1
fi
_peer_sec_key=$(wg genkey)
_peer_pub_key=$(echo "${_peer_sec_key}" | wg pubkey)
_peer_pre_key=$(wg genpsk)
_server_ipv4="$(ip -4 addr | sed -ne 's|^.* inet \([^/]*\)/.* scope global.*$|\1|p' | awk '{print $1}' | head -1)"
echo "[Peer]
PublicKey = ${_peer_pub_key}
PresharedKey = ${_peer_pre_key}
AllowedIPs = ${BG_WG_SUBNET_PREFIX}.${_vpn_octet}.${_new_octet}/${BG_WG_PEER_SUBNET_MASK}" >>"$_vpn_file"
echo
echo "=== NEW CLIENT CONFIGURATION ==="
echo "Location: $_peer_file"
echo "================================"
echo
echo "[Interface]
PrivateKey = ${_peer_sec_key}
Address = ${BG_WG_SUBNET_PREFIX}.${_vpn_octet}.${_new_octet}" >"$_peer_file"
echo "[Peer]
PublicKey = ${_server_pub_key}
PresharedKey = ${_peer_pre_key}
AllowedIPs = ${BG_WG_SUBNET_PREFIX}.${_vpn_octet}.0/${BG_WG_INTERFACE_SUBNET_MASK}
Endpoint = ${_server_ipv4}:${_server_port}
PersistentKeepalive = 25" >>"$_peer_file"
while read -r line; do
echo "$line"
done <"$_peer_file"
echo
echo "================================"
echo
_vpn_restart "$_vpn_name"
}
if ! _check_forwarding; then
printf "Forwarding is not enabled, enable in '$BP_SYSCTL'? [y/n]: "
read -r _opt
case "$_opt" in
y | Y) _enable_forwarding ;;
*) exit 1 ;;
esac
fi
case "$OPT_TARGET" in
vpn)
case "$OPT_ACTION" in
new) _vpn_new "$OPT_ARG" ;;
rm) _vpn_rm "$OPT_ARG" ;;
list) _vpn_list ;;
"") _vpn_list ;;
*) _vpn_new "$OPT_ACTION" ;;
esac
;;
peer)
case "$OPT_ACTION" in
new) _peer_new "$OPT_ARG" ;;
rm) _peer_rm "$OPT_ARG" ;;
list) _peer_list ;;
"") _peer_list ;;
*) _print_help ;;
esac
;;
*) _print_help ;;
esac