146 lines
4.0 KiB
Bash
Executable File
146 lines
4.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -Eeuo pipefail
|
|
umask 077
|
|
|
|
hostname_value="${TPROXY_HOSTNAME:-}"
|
|
public_ip="${MTPROXY_PUBLIC_IP:-}"
|
|
workers="${MTPROXY_WORKERS:-1}"
|
|
max_connections="${MTPROXY_MAX_CONNECTIONS:-4096}"
|
|
|
|
if [[ ! "$hostname_value" =~ ^[a-z0-9]([a-z0-9.-]*[a-z0-9])?$ ]] ||
|
|
[[ "$hostname_value" != *.* ]]; then
|
|
echo "TPROXY_HOSTNAME must be a lowercase DNS hostname" >&2
|
|
exit 2
|
|
fi
|
|
|
|
valid_ipv4() {
|
|
local ip=$1 octet
|
|
local -a octets
|
|
local IFS=.
|
|
read -r -a octets <<<"$ip"
|
|
[[ ${#octets[@]} -eq 4 ]] || return 1
|
|
for octet in "${octets[@]}"; do
|
|
[[ "$octet" =~ ^[0-9]{1,3}$ ]] || return 1
|
|
((10#$octet <= 255)) || return 1
|
|
done
|
|
}
|
|
|
|
if ! valid_ipv4 "$public_ip"; then
|
|
echo "MTPROXY_PUBLIC_IP must be a public IPv4 address" >&2
|
|
exit 2
|
|
fi
|
|
if [[ ! "$workers" =~ ^[1-9][0-9]*$ ]] || ((workers > 256)); then
|
|
echo "MTPROXY_WORKERS must be between 1 and 256" >&2
|
|
exit 2
|
|
fi
|
|
if [[ ! "$max_connections" =~ ^[1-9][0-9]*$ ]]; then
|
|
echo "MTPROXY_MAX_CONNECTIONS must be positive" >&2
|
|
exit 2
|
|
fi
|
|
|
|
install -d -o root -g root -m 0700 /data/mtproxy
|
|
install -d -o tproxy -g tproxy -m 0700 /data/tproxy /run/tproxy
|
|
|
|
atomic_download() {
|
|
local url=$1 destination=$2 minimum_size=$3 required_pattern=$4 temporary
|
|
temporary="${destination}.new"
|
|
rm -f "$temporary"
|
|
curl --fail --silent --show-error --location \
|
|
--proto '=https' --proto-redir '=https' --tlsv1.2 \
|
|
--output "$temporary" "$url"
|
|
[[ $(wc -c <"$temporary") -ge $minimum_size ]]
|
|
grep -q "$required_pattern" "$temporary"
|
|
chmod 0600 "$temporary"
|
|
mv -f "$temporary" "$destination"
|
|
}
|
|
|
|
atomic_download \
|
|
https://core.telegram.org/getProxySecret \
|
|
/data/mtproxy/proxy-secret 128 '.'
|
|
atomic_download \
|
|
https://core.telegram.org/getProxyConfig \
|
|
/data/mtproxy/proxy-multi.conf 100 '^proxy_for '
|
|
chown root:mtproxy /data/mtproxy/proxy-secret /data/mtproxy/proxy-multi.conf
|
|
chmod 0640 /data/mtproxy/proxy-secret /data/mtproxy/proxy-multi.conf
|
|
|
|
if [[ ! -s /data/client-secret ]]; then
|
|
openssl rand -hex 16 > /data/client-secret
|
|
fi
|
|
client_secret="$(tr -d '\r\n' </data/client-secret)"
|
|
if [[ ! "$client_secret" =~ ^[0-9a-f]{32}$ ]]; then
|
|
echo "persisted client secret is invalid" >&2
|
|
exit 2
|
|
fi
|
|
chown root:root /data/client-secret
|
|
chmod 0600 /data/client-secret
|
|
|
|
if [[ ! -s /data/tproxy/token.key ]]; then
|
|
head -c 32 /dev/urandom > /data/tproxy/token.key
|
|
fi
|
|
chown tproxy:tproxy /data/tproxy/token.key
|
|
chmod 0400 /data/tproxy/token.key
|
|
|
|
cat > /data/tproxy/config.json <<JSON
|
|
{
|
|
"public_hostname": "$hostname_value",
|
|
"base_path": "",
|
|
"listen": "127.0.0.1:8080",
|
|
"admin_listen": "127.0.0.1:8081",
|
|
"public_dir": "/srv/tproxy-site",
|
|
"token_key_file": "/data/tproxy/token.key",
|
|
"static_routes": "exact",
|
|
"profiles_file": "/run/tproxy/profiles.json",
|
|
"enable_pprof": false
|
|
}
|
|
JSON
|
|
|
|
cat > /run/tproxy/profiles.json <<JSON
|
|
{"profiles":[{"name":"default","secret":"$client_secret","backend":"127.0.0.1:2398","carrier_mode":"websocket"}]}
|
|
JSON
|
|
|
|
chown tproxy:tproxy /data/tproxy/config.json /run/tproxy/profiles.json
|
|
chmod 0400 /data/tproxy/config.json /run/tproxy/profiles.json
|
|
|
|
runuser -u tproxy -- /usr/local/bin/tproxy-server \
|
|
-config /data/tproxy/config.json \
|
|
-profiles-file /run/tproxy/profiles.json -check
|
|
|
|
local_ip="$(hostname -I | tr ' ' '\n' | awk '/^[0-9]+\./ {print; exit}')"
|
|
if ! valid_ipv4 "$local_ip"; then
|
|
echo "could not determine the container IPv4 address" >&2
|
|
exit 1
|
|
fi
|
|
|
|
/usr/local/bin/mtproto-proxy \
|
|
-u mtproxy \
|
|
-p 8888 \
|
|
-H 2398 \
|
|
-S "$client_secret" \
|
|
--nat-info "$local_ip:$public_ip" \
|
|
--aes-pwd /data/mtproxy/proxy-secret /data/mtproxy/proxy-multi.conf \
|
|
-M "$workers" \
|
|
-C "$max_connections" &
|
|
mtproxy_pid=$!
|
|
|
|
runuser -u tproxy -- /usr/local/bin/tproxy-server \
|
|
-config /data/tproxy/config.json &
|
|
relay_pid=$!
|
|
|
|
runuser -u tproxy -- env TPROXY_HOSTNAME="$hostname_value" \
|
|
/usr/local/bin/tproxy-ingress &
|
|
ingress_pid=$!
|
|
|
|
stop_all() {
|
|
trap - EXIT TERM INT
|
|
kill -TERM "$ingress_pid" "$relay_pid" "$mtproxy_pid" 2>/dev/null || true
|
|
wait "$ingress_pid" "$relay_pid" "$mtproxy_pid" 2>/dev/null || true
|
|
}
|
|
trap stop_all EXIT TERM INT
|
|
|
|
set +e
|
|
wait -n "$mtproxy_pid" "$relay_pid" "$ingress_pid"
|
|
status=$?
|
|
set -e
|
|
exit "$status"
|