From 11440fab176db73640c4ea3b87cb0b6a9390314f Mon Sep 17 00:00:00 2001 From: Teddysun Date: Sat, 15 Feb 2020 13:27:27 +0900 Subject: [PATCH] Added MTProxy (Telegram Messenger MTProto proxy) Docker Image --- docker/mtproxy/Dockerfile | 30 +++++++ docker/mtproxy/Dockerfile.architecture | 30 +++++++ docker/mtproxy/README.md | 85 +++++++++++++++++++ docker/mtproxy/entrypoint.sh | 111 +++++++++++++++++++++++++ 4 files changed, 256 insertions(+) create mode 100644 docker/mtproxy/Dockerfile create mode 100644 docker/mtproxy/Dockerfile.architecture create mode 100644 docker/mtproxy/README.md create mode 100644 docker/mtproxy/entrypoint.sh diff --git a/docker/mtproxy/Dockerfile b/docker/mtproxy/Dockerfile new file mode 100644 index 0000000..930d180 --- /dev/null +++ b/docker/mtproxy/Dockerfile @@ -0,0 +1,30 @@ +# Dockerfile for MTProxy based alpine +# Copyright (C) 2020 Teddysun +# Reference URL: +# https://github.com/TelegramMessenger/MTProxy + +FROM alpine:latest AS builder +WORKDIR /root +COPY patches /root/patches +RUN set -ex \ + && apk add --no-cache git build-base linux-headers musl-dev openssl-dev zlib-dev \ + && git clone https://github.com/TelegramMessenger/MTProxy.git \ + && cd MTProxy \ + && patch -p0 -i /root/patches/randr_compat.patch \ + && make + +FROM alpine:latest +LABEL maintainer="Teddysun " + +RUN set -ex \ + && apk add --no-cache curl tzdata + +COPY entrypoint.sh / +COPY --from=builder /root/MTProxy/objs/bin/mtproto-proxy /usr/bin + +ENV TZ=Asia/Shanghai +EXPOSE 443 2398 +VOLUME /data +WORKDIR /data +ENTRYPOINT ["/entrypoint.sh"] +CMD [ "--port", "2398", "--http-ports", "443", "--slaves", "2", "--max-special-connections", "60000", "--allow-skip-dh" ] \ No newline at end of file diff --git a/docker/mtproxy/Dockerfile.architecture b/docker/mtproxy/Dockerfile.architecture new file mode 100644 index 0000000..eec3458 --- /dev/null +++ b/docker/mtproxy/Dockerfile.architecture @@ -0,0 +1,30 @@ +# Dockerfile for MTProxy based alpine +# Copyright (C) 2020 Teddysun +# Reference URL: +# https://github.com/TelegramMessenger/MTProxy + +FROM --platform=${TARGETPLATFORM} alpine:latest AS builder +WORKDIR /root +COPY patches /root/patches +RUN set -ex \ + && apk add --no-cache git build-base linux-headers musl-dev openssl-dev zlib-dev \ + && git clone https://github.com/TelegramMessenger/MTProxy.git \ + && cd MTProxy \ + && patch -p0 -i /root/patches/randr_compat.patch \ + && make + +FROM --platform=${TARGETPLATFORM} alpine:latest +LABEL maintainer="Teddysun " + +RUN set -ex \ + && apk add --no-cache curl tzdata + +COPY entrypoint.sh / +COPY --from=builder /root/MTProxy/objs/bin/mtproto-proxy /usr/bin + +ENV TZ=Asia/Shanghai +EXPOSE 443 2398 +VOLUME /data +WORKDIR /data +ENTRYPOINT ["/entrypoint.sh"] +CMD [ "--port", "2398", "--http-ports", "443", "--slaves", "2", "--max-special-connections", "60000", "--allow-skip-dh" ] \ No newline at end of file diff --git a/docker/mtproxy/README.md b/docker/mtproxy/README.md new file mode 100644 index 0000000..54e0ef4 --- /dev/null +++ b/docker/mtproxy/README.md @@ -0,0 +1,85 @@ +## MTProxy Docker Image by Teddysun + +The [Telegram Messenger MTProto proxy][1] is a zero-configuration container that automatically sets up a proxy server that speaks Telegram's native MTProto. + +This Docker Image forked by [alexdoesh](https://github.com/alexdoesh/mtproxy) + +Docker images are built for quick deployment in various computing cloud providers. + +For more information on docker and containerization technologies, refer to [official document][2]. + +## Prepare the host + +If you need to install docker by yourself, follow the [official installation guide][3]. + +## Pull the image + +```bash +$ docker pull teddysun/mtproxy +``` + +This pulls the latest release of MTProxy. + +It can be found at [Docker Hub][4]. + +## Start a container + +You **must create a directory** `/etc/mtproxy` in host at first: + +``` +$ mkdir -p /etc/mtproxy +``` + +To start the proxy all you need to do is below: + +`docker run -d -p443:443 --name=mtproxy --restart=always -v /etc/mtproxy:/data teddysun/mtproxy` + +The container's log output (`docker logs mtproxy`) will contain the links to paste into the Telegram app: + +``` +[+] Using the explicitly passed secret: '00baadf00d15abad1deaa515baadcafe'. +[+] Saving it to /data/secret. +[*] Final configuration: +[*] Secret 1: 00baadf00d15abad1deaa515baadcafe +[*] tg:// link for secret 1 auto configuration: : tg://proxy?server=3.14.15.92&port=443&secret=00baadf00d15abad1deaa515baadcafe +[*] t.me link for secret 1: tg://proxy?server=3.14.15.92&port=443&secret=00baadf00d15abad1deaa515baadcafe +[*] Tag: no tag +[*] External IP: 3.14.15.92 +[*] Make sure to fix the links in case you run the proxy on a different port. +``` + +**Warning**: The port number `443` must be opened in firewall. + +The secret will persist across container upgrades in a volume. + +It is a mandatory configuration parameter: if not provided, it will be generated automatically at container start. + +You may forward any other port to the container's 443: be sure to fix the automatic configuration links if you do so. + +Please note that the proxy gets the Telegram core IP addresses at the start of the container. We try to keep the changes to a minimum, but you should restart the container about once a day, just in case. + +## Registering your proxy + +Once your MTProxy server is up and running go to [@MTProxybot](https://t.me/mtproxybot) and register your proxy with Telegram to gain access to usage statistics and monetization. + +## Custom configuration + +If you need to specify a custom secret (say, if you are deploying multiple proxies with DNS load-balancing), you may pass the SECRET environment variable as 16 bytes in lower-case hexidecimals: + +`docker run -d -p443:443 -v /etc/mtproxy:/data -e SECRET=00baadf00d15abad1deaa51sbaadcafe teddysun/mtproxy` + +## Monitoring + +The MTProto proxy server exports internal statistics as tab-separated values over the http://localhost:2398/stats endpoint. + +Please note that this endpoint is available only from localhost: depending on your configuration, you may need to collect the statistics with `docker exec mtproxy curl http://localhost:2398/stats`. + +* `ready_targets`: number of Telegram core servers the proxy will try to connect to. +* `active_targets`: number of Telegram core servers the proxy is actually connected to. Should be equal to ready_targets. +* `total_special_connections`: number of inbound client connections +* `total_max_special_connections`: the upper limit on inbound connections. Is equal to 60000 multiplied by worker count. + +[1]: https://github.com/TelegramMessenger/MTProxy +[2]: https://docs.docker.com/ +[3]: https://docs.docker.com/install/ +[4]: https://hub.docker.com/r/teddysun/mtproxy/ \ No newline at end of file diff --git a/docker/mtproxy/entrypoint.sh b/docker/mtproxy/entrypoint.sh new file mode 100644 index 0000000..63ff06c --- /dev/null +++ b/docker/mtproxy/entrypoint.sh @@ -0,0 +1,111 @@ +#!/bin/sh +if [ ! -z "$DEBUG" ]; then set -x; fi +mkdir /data 2>/dev/null >/dev/null +RANDOM=$(printf "%d" "0x$(head -c4 /dev/urandom | od -t x1 -An | tr -d ' ')") + +if [ -z "$WORKERS" ]; then + WORKERS=1 +fi + +SECRET_CMD="" +if [ ! -z "$SECRET" ]; then + echo "[+] Using the explicitly passed secret: '$SECRET'." +elif [ -f /data/secret ]; then + SECRET="$(cat /data/secret)" + echo "[+] Using the secret in /data/secret: '$SECRET'." +else + if [[ ! -z "$SECRET_COUNT" ]]; then + if [[ "$SECRET_COUNT" -le 1 || "$SECRET_COUNT" -ge 16 ]]; then + echo "[F] Can generate between 1 and 16 secrets." + exit 5 + fi + else + SECRET_COUNT="1" + fi + + echo "[+] No secret passed. Will generate $SECRET_COUNT random ones." + SECRET="$(dd if=/dev/urandom bs=16 count=1 2>&1 | od -tx1 | head -n1 | tail -c +9 | tr -d ' ')" + for pass in $(seq 2 $SECRET_COUNT); do + SECRET="$SECRET,$(dd if=/dev/urandom bs=16 count=1 2>&1 | od -tx1 | head -n1 | tail -c +9 | tr -d ' ')" + done +fi + +if echo "$SECRET" | grep -qE '^[0-9a-fA-F]{32}(,[0-9a-fA-F]{32}){0,15}$'; then + SECRET="$(echo "$SECRET" | tr '[:upper:]' '[:lower:]')" + SECRET_CMD="-S $(echo "$SECRET" | sed 's/,/ -S /g')" + echo -- "$SECRET_CMD" > /data/secret_cmd + echo "$SECRET" > /data/secret +else + echo '[F] Bad secret format: should be 32 hex chars (for 16 bytes) for every secret; secrets should be comma-separated.' + exit 1 +fi + +if [ ! -z "$TAG" ]; then + echo "[+] Using the explicitly passed tag: '$TAG'." +fi + +TAG_CMD="" +if [[ ! -z "$TAG" ]]; then + if echo "$TAG" | grep -qE '^[0-9a-fA-F]{32}$'; then + TAG="$(echo "$TAG" | tr '[:upper:]' '[:lower:]')" + TAG_CMD="-P $TAG" + else + echo '[!] Bad tag format: should be 32 hex chars (for 16 bytes).' + echo '[!] Continuing.' + fi +fi + +REMOTE_CONFIG=/data/proxy-multi.conf +curl -s https://core.telegram.org/getProxyConfig -o ${REMOTE_CONFIG} || { + echo '[F] Cannot download proxy configuration from Telegram servers.' + exit 2 +} + +REMOTE_SECRET=/data/proxy-secret +curl -s https://core.telegram.org/getProxySecret -o ${REMOTE_SECRET} || { + echo '[F] Cannot download proxy secret from Telegram servers.' + exit 5 +} + +if [ ! -z "$EXTERNAL_IP" ]; then + echo "[+] Using the explicitly passed external IP: ${EXTERNAL_IP}." +else + EXTERNAL_IP="$(curl -s -4 "ipv4.icanhazip.com")" + if [[ -z "$EXTERNAL_IP" ]]; then + echo "[F] Cannot determine external IP address." + exit 3 + else + echo "[+] Using the detected external IP: ${EXTERNAL_IP}." + fi +fi + +if [ ! -z "$INTERNAL_IP" ]; then + echo "[+] Using the explicitly passed internal IP: ${INTERNAL_IP}." +else + INTERNAL_IP="$(ip -4 route get 8.8.8.8 | grep '^8\.8\.8\.8\s' | grep -Eo 'src\s+\d+\.\d+\.\d+\.\d+' | awk '{print $2}')" + if [[ -z "$INTERNAL_IP" ]]; then + echo "[F] Cannot determine internal IP address." + exit 4 + else + echo "[+] Using the detected internal IP: ${INTERNAL_IP}." + fi +fi + +echo "[*] Final configuration:" +I=1 +echo "$SECRET" | tr ',' '\n' | while read S; do + echo "[*] Secret $I: $S" + echo "[*] tg:// link for secret $I auto configuration: tg://proxy?server=${EXTERNAL_IP}&port=443&secret=${S}" + echo "[*] t.me link for secret $I: https://t.me/proxy?server=${EXTERNAL_IP}&port=443&secret=${S}" + I=$(($I+1)) +done + +[ ! -z "$TAG" ] && echo "[*] Tag: $TAG" || echo "[*] Tag: no tag" +echo "[*] External IP: ${EXTERNAL_IP}" +echo "[*] Make sure to fix the links in case you run the proxy on a different port." +echo +echo '[+] Starting proxy...' +sleep 1 + +# start mtproto-proxy +exec mtproto-proxy "$@" --aes-pwd ${REMOTE_SECRET} --user root ${REMOTE_CONFIG} --nat-info "$INTERNAL_IP:$EXTERNAL_IP" ${SECRET_CMD} ${TAG_CMD} \ No newline at end of file