Improve user input

- On servers with multiple IPv4 addresses, check if one of them
  matches the server's public IP. If so, select that IP and skip
  the IP selection question.
- If the server is behind NAT, try to find its public IP and
  ask the user only if the IP cannot be found.
- Cleanup
This commit is contained in:
hwdsl2 2022-09-20 01:29:41 -05:00
parent 608822a146
commit 0ce6897321

View File

@ -101,6 +101,11 @@ check_ip() {
printf '%s' "$1" | tr -d '\n' | grep -Eq "$IP_REGEX"
}
find_public_ip() {
# Get public IP and sanitize with grep
get_public_ip=$(grep -m 1 -oE '^[0-9]{1,3}(\.[0-9]{1,3}){3}$' <<< "$(wget -T 10 -t 1 -4qO- "http://ip1.dynupdate.no-ip.com/" || curl -m 10 -4Ls "http://ip1.dynupdate.no-ip.com/")")
}
abort_and_exit () {
echo "Abort. No changes were made." >&2
exit 1
@ -156,10 +161,10 @@ new_client_dns () {
echo " 5) Quad9"
echo " 6) AdGuard DNS"
echo " 7) Custom"
read -p "DNS server [2]: " dns
read -rp "DNS server [2]: " dns
until [[ -z "$dns" || "$dns" =~ ^[1-7]$ ]]; do
echo "$dns: invalid selection."
read -p "DNS server [2]: " dns
read -rp "DNS server [2]: " dns
done
# DNS
case "$dns" in
@ -281,31 +286,43 @@ if [[ ! -e /etc/wireguard/wg0.conf ]]; then
if [[ $(ip -4 addr | grep inet | grep -vEc '127(\.[0-9]{1,3}){3}') -eq 1 ]]; then
ip=$(ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}')
else
number_of_ip=$(ip -4 addr | grep inet | grep -vEc '127(\.[0-9]{1,3}){3}')
echo
echo "Which IPv4 address should be used?"
ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' | nl -s ') '
read -p "IPv4 address [1]: " ip_number
until [[ -z "$ip_number" || "$ip_number" =~ ^[0-9]+$ && "$ip_number" -le "$number_of_ip" ]]; do
echo "$ip_number: invalid selection."
read -p "IPv4 address [1]: " ip_number
done
[[ -z "$ip_number" ]] && ip_number="1"
ip=$(ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' | sed -n "$ip_number"p)
find_public_ip
ip_list=$(ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}')
ip_match=0
while IFS= read -r line; do
if [ "$line" = "$get_public_ip" ]; then
ip_match=1
ip="$line"
fi
done <<< "$ip_list"
if [ "$ip_match" = 0 ]; then
number_of_ip=$(ip -4 addr | grep inet | grep -vEc '127(\.[0-9]{1,3}){3}')
echo
echo "Which IPv4 address should be used?"
ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' | nl -s ') '
read -rp "IPv4 address [1]: " ip_number
until [[ -z "$ip_number" || "$ip_number" =~ ^[0-9]+$ && "$ip_number" -le "$number_of_ip" ]]; do
echo "$ip_number: invalid selection."
read -rp "IPv4 address [1]: " ip_number
done
[[ -z "$ip_number" ]] && ip_number="1"
ip=$(ip -4 addr | grep inet | grep -vE '127(\.[0-9]{1,3}){3}' | cut -d '/' -f 1 | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}' | sed -n "$ip_number"p)
fi
fi
# If $ip is a private IP address, the server must be behind NAT
if echo "$ip" | grep -qE '^(10\.|172\.1[6789]\.|172\.2[0-9]\.|172\.3[01]\.|192\.168)'; then
echo
echo "This server is behind NAT. What is the public IPv4 address or hostname?"
# Get public IP and sanitize with grep
get_public_ip=$(grep -m 1 -oE '^[0-9]{1,3}(\.[0-9]{1,3}){3}$' <<< "$(wget -T 10 -t 1 -4qO- "http://ip1.dynupdate.no-ip.com/" || curl -m 10 -4Ls "http://ip1.dynupdate.no-ip.com/")")
read -p "Public IPv4 address / hostname [$get_public_ip]: " public_ip
# If the checkip service is unavailable and user didn't provide input, ask again
until [[ -n "$get_public_ip" || -n "$public_ip" ]]; do
echo "Invalid input."
read -p "Public IPv4 address / hostname: " public_ip
done
[[ -z "$public_ip" ]] && public_ip="$get_public_ip"
find_public_ip
if [ -z "$get_public_ip" ]; then
echo
echo "This server is behind NAT. What is the public IPv4 address?"
read -rp "Public IPv4 address: " public_ip
until check_ip "$public_ip"; do
echo "Invalid input."
read -rp "Public IPv4 address: " public_ip
done
else
public_ip="$get_public_ip"
fi
fi
# If system has a single IPv6, it is selected automatically
if [[ $(ip -6 addr | grep -c 'inet6 [23]') -eq 1 ]]; then
@ -317,25 +334,25 @@ if [[ ! -e /etc/wireguard/wg0.conf ]]; then
echo
echo "Which IPv6 address should be used?"
ip -6 addr | grep 'inet6 [23]' | cut -d '/' -f 1 | grep -oE '([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}' | nl -s ') '
read -p "IPv6 address [1]: " ip6_number
read -rp "IPv6 address [1]: " ip6_number
until [[ -z "$ip6_number" || "$ip6_number" =~ ^[0-9]+$ && "$ip6_number" -le "$number_of_ip6" ]]; do
echo "$ip6_number: invalid selection."
read -p "IPv6 address [1]: " ip6_number
read -rp "IPv6 address [1]: " ip6_number
done
[[ -z "$ip6_number" ]] && ip6_number="1"
ip6=$(ip -6 addr | grep 'inet6 [23]' | cut -d '/' -f 1 | grep -oE '([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}' | sed -n "$ip6_number"p)
fi
echo
echo "What port should WireGuard listen to?"
read -p "Port [51820]: " port
read -rp "Port [51820]: " port
until [[ -z "$port" || "$port" =~ ^[0-9]+$ && "$port" -le 65535 ]]; do
echo "$port: invalid port."
read -p "Port [51820]: " port
read -rp "Port [51820]: " port
done
[[ -z "$port" ]] && port="51820"
echo
echo "Enter a name for the first client:"
read -p "Name [client]: " unsanitized_client
read -rp "Name [client]: " unsanitized_client
# Allow a limited set of characters to avoid conflicts
client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client")
[[ -z "$client" ]] && client="client"
@ -547,22 +564,22 @@ else
echo " 2) Remove an existing client"
echo " 3) Remove WireGuard"
echo " 4) Exit"
read -p "Option: " option
read -rp "Option: " option
until [[ "$option" =~ ^[1-4]$ ]]; do
echo "$option: invalid selection."
read -p "Option: " option
read -rp "Option: " option
done
case "$option" in
1)
echo
echo "Provide a name for the client:"
read -p "Name: " unsanitized_client
read -rp "Name: " unsanitized_client
[ -z "$unsanitized_client" ] && abort_and_exit
# Allow a limited set of characters to avoid conflicts
client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client")
while [[ -z "$client" ]] || grep -q "^# BEGIN_PEER $client$" /etc/wireguard/wg0.conf; do
echo "$client: invalid name."
read -p "Name: " unsanitized_client
read -rp "Name: " unsanitized_client
[ -z "$unsanitized_client" ] && abort_and_exit
client=$(sed 's/[^0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-]/_/g' <<< "$unsanitized_client")
done
@ -590,19 +607,19 @@ else
echo
echo "Select the client to remove:"
grep '^# BEGIN_PEER' /etc/wireguard/wg0.conf | cut -d ' ' -f 3 | nl -s ') '
read -p "Client: " client_number
read -rp "Client: " client_number
[ -z "$client_number" ] && abort_and_exit
until [[ "$client_number" =~ ^[0-9]+$ && "$client_number" -le "$number_of_clients" ]]; do
echo "$client_number: invalid selection."
read -p "Client: " client_number
read -rp "Client: " client_number
[ -z "$client_number" ] && abort_and_exit
done
client=$(grep '^# BEGIN_PEER' /etc/wireguard/wg0.conf | cut -d ' ' -f 3 | sed -n "$client_number"p)
echo
read -p "Confirm $client removal? [y/N]: " remove
read -rp "Confirm $client removal? [y/N]: " remove
until [[ "$remove" =~ ^[yYnN]*$ ]]; do
echo "$remove: invalid selection."
read -p "Confirm $client removal? [y/N]: " remove
read -rp "Confirm $client removal? [y/N]: " remove
done
if [[ "$remove" =~ ^[yY]$ ]]; then
echo
@ -628,10 +645,10 @@ else
;;
3)
echo
read -p "Confirm WireGuard removal? [y/N]: " remove
read -rp "Confirm WireGuard removal? [y/N]: " remove
until [[ "$remove" =~ ^[yYnN]*$ ]]; do
echo "$remove: invalid selection."
read -p "Confirm WireGuard removal? [y/N]: " remove
read -rp "Confirm WireGuard removal? [y/N]: " remove
done
if [[ "$remove" =~ ^[yY]$ ]]; then
echo