Last active
September 7, 2024 06:44
-
-
Save seriyps/dc00ad91bfd8a2058f30845cd0daed83 to your computer and use it in GitHub Desktop.
Interactive MTProto proxy installer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Automatic interactive installer for mtproto proxy https://github.com/seriyps/mtproto_proxy | |
# Supported OS: | |
# - Ubuntu 18.xx | |
# - Ubuntu 19.xx | |
# - Ubuntu 20.xx | |
# - Ubuntu 21.xx | |
# - Ubuntu 22.xx | |
# - Debian 11 bullseye | |
# - Debian 10 buster | |
# - Debian 9 stretch | |
# - Debinn 8 jessie (not well-tested) | |
# - CentOS 7 | |
RED='\033[0;31m' | |
GR='\033[0;32m' | |
YE='\033[0;33m' | |
NC='\033[0m' | |
WORKDIR=`pwd` | |
SRC_DIR=mtproto_proxy | |
SELF="$0" | |
info() { | |
echo -e "${GR}INFO${NC}: $1" | |
} | |
warn() { | |
echo -e "${YE}WARNING${NC}: $1" | |
} | |
error() { | |
echo -e "${RED}ERROR${NC}: $1" 1>&2 | |
exit 1 | |
} | |
usage() { | |
echo "MTProto proxy installer. | |
Install proxy: | |
${SELF} -p <port> -s <secret> -t <ad tag> -a dd -a tls -d <fake-tls domain> | |
Upgrade code to the latest version and restart, keeping config unchanged: | |
${SELF} upgrade | |
Interactively generate new config and reload proxy settings: | |
${SELF} reconfigure -p <port> -s <secret> -t <ad tag> -a dd -a tls -d <fake-tls domain> | |
Reload proxy settings after manual changes in config/prod-sys.cnfig: | |
${SELF} reload | |
" | |
} | |
to_hex() { | |
od -A n -t x1 -w128 | sed 's/ //g' | |
} | |
case "$1" in | |
reconfigure|reload|upgrade|install) | |
CMD="$1" | |
shift | |
;; | |
*) | |
CMD="install" | |
esac | |
PORT=${MTP_PORT:-""} | |
SECRET=${MTP_SECRET:-""} | |
TAG=${MTP_TAG:-""} | |
DD_ONLY=${MTP_DD_ONLY:-""} | |
TLS_ONLY=${MTP_TLS_ONLY:-""} | |
TLS_DOMAIN=${MTP_TLS_DOMAIN:-""} | |
# check command line options | |
while getopts "p:s:t:a:d:h" o; do | |
case "${o}" in | |
p) | |
PORT=${OPTARG} | |
;; | |
s) | |
SECRET=${OPTARG} | |
;; | |
t) | |
TAG=${OPTARG} | |
;; | |
a) | |
case "${OPTARG}" in | |
"dd") | |
DD_ONLY="y" | |
;; | |
"tls") | |
TLS_ONLY="y" | |
;; | |
*) | |
error "Invalid -a value: '${OPTARG}'" | |
esac | |
;; | |
d) | |
TLS_DOMAIN=${OPTARG} | |
;; | |
h) | |
usage | |
exit 0 | |
esac | |
done | |
echo "Interactive MTProto proxy installer." | |
echo "You can make the process fully automated by calling this script as 'echo \"y\ny\ny\ny\ny\ny\" | $0'." | |
echo "Try $0 -h for more options." | |
set -e | |
source /etc/os-release | |
info "Detected OS is ${ID} ${VERSION_ID}" | |
do_configure_os() { | |
# We need at least 'make' 'sed' 'diff' 'od' 'install' 'tar' 'base64' 'awk' | |
case "${ID}-${VERSION_ID}" in | |
ubuntu-19.*|ubuntu-20.*|ubuntu-21.*|ubuntu-22.*|debian-10|debian-11) | |
info "Installing required APT packages" | |
sudo apt update | |
sudo apt install erlang-nox erlang-dev make sed diffutils tar | |
;; | |
debian-9|debian-8|ubuntu-18.*) | |
info "Installing extra repositories" | |
curl -L https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb -o erlang-solutions_1.0_all.deb | |
sudo dpkg -i erlang-solutions_1.0_all.deb | |
sudo apt update | |
info "Installing required APT packages" | |
sudo apt install erlang-nox erlang-dev make sed diffutils tar | |
;; | |
centos-7) | |
info "Installing extra repositories" | |
sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \ | |
wget \ | |
https://packages.erlang-solutions.com/erlang-solutions-1.0-1.noarch.rpm | |
info "Installing required RPM packages" | |
sudo yum install chrony erlang-compiler erlang-erts erlang-kernel erlang-stdlib erlang-syntax_tools \ | |
erlang-crypto erlang-inets erlang-sasl erlang-ssl | |
;; | |
*) | |
error "Your OS ${ID} ${VERSION_ID} is not supported!" | |
esac | |
info "Making sure clock synchronization is enabled" | |
if [ `systemctl is-active ntp` = "active" ]; then | |
info "Replacing ntpd with systemd-timesyncd" | |
systemctl disable ntp | |
systemctl stop ntp | |
fi | |
sudo timedatectl set-ntp on | |
info "Current time: `date`" | |
} | |
do_get_source() { | |
info "Downloading proxy source code" | |
curl -L https://github.com/seriyps/mtproto_proxy/archive/master.tar.gz -o mtproto_proxy.tar.gz | |
info "Unpacking source code" | |
tar -xaf mtproto_proxy.tar.gz | |
mv -T --backup=t mtproto_proxy-master $SRC_DIR | |
} | |
# cd mtproto_proxy/ | |
do_build_config() { | |
info "Interactively generating config-file" | |
# So, we ask for port/secret/ad_tag/protocols only if they are not specified via | |
# command-line or env vars | |
if [ -z "${PORT}" ]; then | |
PORT=443 | |
read -p "Use default proxy port 443? [y/n] " yn | |
case $yn in | |
[Nn]*) | |
read -p "Enter port number: 1-32000: " PORT | |
;; | |
*) | |
info "Using default port 443" | |
;; | |
esac | |
fi | |
if [ "${ID}" = "centos" -a "`sudo firewall-cmd --state 2>&1`" = "running" ]; then | |
read -p "Should I configure firewall? | |
'd' to disable firewall completely | |
'n' if you will setup firewall by yourself [y/n/d] " yn | |
case $yn in | |
[Yy]*) | |
info "Opening ${PORT} port" | |
sudo firewall-cmd --zone=public --add-port=${PORT}/tcp --permanent | |
sudo firewall-cmd --reload | |
;; | |
[Dd]*) | |
warning "Stopping firewalld" | |
sudo systemctl stop firewalld | |
sudo systemctl disable firewalld | |
;; | |
*) | |
warn "Please make sure proxy port ${PORT} is open on firewall! | |
Use smth like: | |
firewall-cmd --zone=public --add-port=${PORT}/tcp --permanent | |
firewall-cmd --reload" | |
;; | |
esac | |
fi | |
if [ -z "${SECRET}" ]; then | |
SECRET=`head -c 16 /dev/urandom | to_hex` | |
read -p "Use randomly generated secret '${SECRET}'? [y/n] " yn | |
case $yn in | |
[Nn]*) | |
read -p "Enter your secret: 16 hex characters 0-9a-f: " SECRET | |
;; | |
*) | |
info "Using random secret ${SECRET}" | |
;; | |
esac | |
fi | |
if [ -z "${TAG}" ]; then | |
TAG="8b081275ec12abd306faeb2f13efbdcb" | |
read -p "Use empty @MTProxybot AD TAG? Answer 'n' to set AD TAG [y/n] " yn | |
case $yn in | |
[Nn]*) | |
read -p "Enter your ad tag from @MTProxybot: " TAG | |
;; | |
*) | |
info "Using no AD TAG" | |
esac | |
fi | |
if [ -z "${DD_ONLY}" ]; then | |
DD_ONLY="y" | |
read -p "Enable dd-only mode? (recommended) [y/n] " yn | |
case $yn in | |
[Nn]*) | |
DD_ONLY="" | |
warn "dd-only mode disabled" | |
;; | |
*) | |
info "Using dd-only mode" | |
esac | |
fi | |
if [ -z "${TLS_ONLY}" ]; then | |
TLS_ONLY="y" | |
read -p "Enable TLS-only mode? (recommended) [y/n] " yn | |
case $yn in | |
[Nn]*) | |
TLS_ONLY="" | |
warn "TLS-only mode disabled" | |
;; | |
*) | |
info "Using TLS-only mode" | |
esac | |
fi | |
if [ -z "${TLS_DOMAIN}" -a \( -n "${TLS_ONLY}" -o -z "${DD_ONLY}" \) ]; then | |
# If tls_domain is not set and fake-tls is enabled, ask for domain | |
TLS_DOMAIN="s3.amazonaws.com" | |
read -p "Use '${TLS_DOMAIN}' as domain name for fake-tls? Answer 'n' to change to another [y/n] " yn | |
case $yn in | |
[Nn]*) | |
read -p "Enter domain name: " TLS_DOMAIN | |
;; | |
*) | |
;; | |
esac | |
info "Using '${TLS_DOMAIN}' for fake-TLS SNI" | |
fi | |
PROTO_ARG="" | |
if [ -n "${DD_ONLY}" -a -n "${TLS_ONLY}" ]; then | |
PROTO_ARG='{allowed_protocols, [mtp_fake_tls,mtp_secure]},' | |
elif [ -n "${DD_ONLY}" ]; then | |
PROTO_ARG='{allowed_protocols, [mtp_secure]},' | |
elif [ -n "${TLS_ONLY}" ]; then | |
PROTO_ARG='{allowed_protocols, [mtp_fake_tls]},' | |
fi | |
[ -z "${PORT}" -o -z "${SECRET}" -o -z "${TAG}" ] && \ | |
error "Not enough options: port='${PORT}' secret='${SECRET}' ad_tag='${TAG}'" | |
[ ${PORT} -gt 0 -a ${PORT} -lt 65535 ] || \ | |
error "Invalid port value: ${PORT}" | |
[ -n "`echo $SECRET | grep -x '[[:xdigit:]]\{32\}'`" ] || \ | |
error "Invalid secret. Should be 32 chars of 0-9 a-f" | |
[ -n "`echo $TAG | grep -x '[[:xdigit:]]\{32\}'`" ] || \ | |
error "Invalid tag. Should be 32 chars of 0-9 a-f" | |
[ -z "${TLS_DOMAIN}" -o -n "`echo $TLS_DOMAIN | grep -xE '^([0-9a-z_-]+\.)+[a-z]{2,6}$'`" ] || \ | |
error "Invalid TLS domain '${TLS_DOMAIN}'. Should be valid domain name!" | |
echo ' | |
%% -*- mode: erlang -*- | |
[ | |
{mtproto_proxy, | |
%% see src/mtproto_proxy.app.src for examples. | |
[ | |
'${PROTO_ARG}' | |
{ports, | |
[#{name => mtp_handler_1, | |
listen_ip => "0.0.0.0", | |
port => '${PORT}', | |
secret => <<"'${SECRET}'">>, | |
tag => <<"'${TAG}'">>} | |
]} | |
]}, | |
%% Logging config | |
{lager, | |
[{log_root, "/var/log/mtproto-proxy"}, | |
{crash_log, "crash.log"}, | |
{handlers, | |
[ | |
{lager_console_backend, | |
[{level, critical}]}, | |
{lager_file_backend, | |
[{file, "application.log"}, | |
{level, info}, | |
%% Do fsync only on critical messages | |
{sync_on, critical}, | |
%% If we logged more than X messages in a second, flush the rest | |
{high_water_mark, 300}, | |
%% If we hit hwm and msg queue len is >X, flush the queue | |
{flush_queue, true}, | |
{flush_threshold, 2000}, | |
%% How often to check if log should be rotated | |
{check_interval, 5000}, | |
%% Rotate when file size is 100MB+ | |
{size, 104857600} | |
]} | |
]}]}, | |
{sasl, [{errlog_type, error}]} | |
].' >config/prod-sys.config | |
info "Config is generated with following properties: | |
port=${PORT} secret=${SECRET} tag=${TAG} tls_only=${TLS_ONLY} dd_only=${DD_ONLY} domain=${TLS_DOMAIN}" | |
} | |
do_backup_config() { | |
cp $SRC_DIR/config/prod-sys.config $WORKDIR/prod-sys.config.bak | |
} | |
do_restore_config() { | |
cp $WORKDIR/prod-sys.config.bak config/prod-sys.config | |
} | |
do_reload_config() { | |
sudo make update-sysconfig | |
sudo systemctl reload mtproto-proxy | |
} | |
do_build() { | |
info "Generating Erlang interpreter options" | |
make config/prod-vm.args | |
info "Compiling" | |
make | |
} | |
do_install() { | |
# Try to stop proxy in case this script is run not for the first time | |
sudo systemctl stop mtproto-proxy || true | |
info "Installing" | |
sudo make install | |
info "Starting" | |
sudo systemctl enable mtproto-proxy | |
sudo systemctl start mtproto-proxy | |
} | |
do_print_links() { | |
info "Detecting IP address" | |
IP=`curl -s -4 -m 10 http://ipv4.seriyps.ru || curl -s -4 -m 10 https://digitalresistance.dog/myIp` | |
info "Detected external IP is ${IP}" | |
URL_PREFIX="https://t.me/proxy?server=${IP}&port=${PORT}&secret=" | |
ESCAPED_SECRET=$(echo -n $SECRET | sed 's/../\\x&/g') # bytes | |
ESCAPED_TLS_SECRET="\xee${ESCAPED_SECRET}"${TLS_DOMAIN} | |
BASE64_TLS_SECRET=`echo -ne $ESCAPED_TLS_SECRET | base64 -w 0 | tr '+/' '-_'` | |
HEX_TLS_SECRET=`echo -ne $ESCAPED_TLS_SECRET | to_hex` | |
info "Logs: /var/log/mtproto-proxy/application.log" | |
info "Secret: ${SECRET}" | |
info "Proxy links: | |
Normal: ${URL_PREFIX}${SECRET} | |
Secure: ${URL_PREFIX}dd${SECRET} | |
Fake-TLS hex: ${URL_PREFIX}${HEX_TLS_SECRET} | |
Fake-TLS base64: ${URL_PREFIX}${BASE64_TLS_SECRET} | |
" | |
} | |
# info "Executing $CMD" | |
case "$CMD" in | |
"install") | |
do_configure_os | |
do_get_source | |
cd $SRC_DIR/ | |
do_build_config | |
do_build | |
do_install | |
do_print_links | |
info "Proxy is ready" | |
;; | |
"reconfigure") | |
cd $SRC_DIR/ | |
do_build_config | |
do_reload_config | |
do_print_links | |
info "Config updated" | |
;; | |
"reload") | |
cd $SRC_DIR/ | |
do_reload_config | |
info "Config updated" | |
;; | |
"upgrade") | |
do_backup_config | |
do_get_source | |
cd $SRC_DIR/ | |
do_restore_config | |
do_build | |
do_install | |
info "Code upgraded" | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I forked and modified debian apt install with -y to bypass prompt in the script. I appreciate revising it for public use as well.