openvidu/openvidu-server/docker/utils/discover_my_public_ip.sh

134 lines
3.5 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
#/ Discover the external IP address of the running system.
#/
#/ This script is useful when running from a machine that sits behind a NAT.
#/ Due to how NAT works, machines behind it belong to an internal or private
#/ subnet, with a different address space than the external or public side.
#/
#/ Typically it is possible to make an HTTP request to a number of providers
#/ that offer the external IP in their response body (eg: ifconfig.me). However,
#/ why do a slow and heavy HTTP request, when DNS exists and is much faster?
#/ Well established providers such as OpenDNS or Google offer special hostnames
#/ that, when resolved, will actually return the IP address of the caller.
#/
#/ https://unix.stackexchange.com/questions/22615/how-can-i-get-my-external-ip-address-in-a-shell-script/81699#81699
#/
#/
#/ Arguments
#/ =========
#/
#/ --ipv4
#/
#/ Find the external IPv4 address.
#/ Optional. Default: Enabled.
#/
#/ --ipv6
#/
#/ Find the external IPv6 address.
#/ Optional. Default: Disabled.
# Shell setup
# ===========
# Bash options for strict error checking.
set -o errexit -o errtrace -o pipefail -o nounset
# Trace all commands (to stderr).
#set -o xtrace
# Trap function for unhandled errors.
function on_error {
echo "[$0] ERROR ($?)" >&2
exit 1
2020-04-21 13:00:46 +02:00
}
trap on_error ERR
# Check dependencies.
function check_programs {
local PROGRAMS=(
dig
wget
)
for PROGRAM in "${PROGRAMS[@]}"; do
command -v "$PROGRAM" >/dev/null || {
echo "[$0] ERROR: '$PROGRAM' is not installed; please install it"
exit 1
}
done
}
check_programs
# Parse arguments
# ===============
CFG_IPV4="true"
CFG_IPV6="false"
while [[ $# -gt 0 ]]; do
case "${1-}" in
--ipv4)
CFG_IPV4="true"
CFG_IPV6="false"
;;
--ipv6)
CFG_IPV4="false"
CFG_IPV6="true"
;;
*)
echo "[$0] Invalid argument: '${1-}'" >&2
exit 1
;;
esac
shift
done
# Discover external IP address
# ============================
if [[ "$CFG_IPV4" == "true" ]]; then
COMMANDS=(
'dig @resolver1.opendns.com myip.opendns.com A -4 +short'
'dig @ns1.google.com o-o.myaddr.l.google.com TXT -4 +short | tr -d \"'
'dig @1.1.1.1 whoami.cloudflare TXT CH -4 +short | tr -d \"'
'dig @ns1-1.akamaitech.net whoami.akamai.net A -4 +short'
'wget --quiet -4 -O - ifconfig.co'
)
function is_valid_ip {
# Check if the input looks like an IPv4 address.
# Doesn't check if the actual values are valid; assumes they are.
echo "$1" | grep --perl-regexp --quiet '^(\d{1,3}\.){3}\d{1,3}$'
}
elif [[ "$CFG_IPV6" == "true" ]]; then
COMMANDS=(
'dig @resolver1.opendns.com myip.opendns.com AAAA -6 +short'
'dig @ns1.google.com o-o.myaddr.l.google.com TXT -6 +short | tr -d \"'
'dig @2606:4700:4700::1111 whoami.cloudflare TXT CH -6 +short | tr -d \"'
'wget --quiet -6 -O - ifconfig.co'
)
function is_valid_ip {
# Check if the input looks like an IPv6 address.
# It's almost impossible to check the IPv6 representation because it
# varies wildly, so just check that there are at least 2 colons.
[[ "$(echo "$1" | awk -F':' '{print NF-1}')" -ge 2 ]]
}
fi
2020-04-21 13:00:46 +02:00
for COMMAND in "${COMMANDS[@]}"; do
if IP="$(eval "$COMMAND")" && is_valid_ip "$IP"; then
echo "$IP"
exit 0
2020-04-21 13:00:46 +02:00
fi
done
echo "[$0] Discovery failed" >&2
exit 1