baicai

白菜

一个勤奋的代码搬运工!

Setting up a reverse proxy for Telegram Bot API.

title: "Setting up a Reverse Proxy for Telegram Bot API"
slug: "nginx_tgapi_proxy"
date: 2023-09-19T22:28:07+08:00
type: posts
draft: false
categories: ["Using Software","Nginx"]
tags: ["Technical Sharing","nginx","proxy","telegram"]

description: ""#


Due to certain reasons, configuring epusdt requires the use of a reverse proxy address for tg!

#telegram proxy url (for mainland servers, a foreign server can be used as a reverse proxy for tg), if running on a foreign server, no need to fill in
tg_proxy=

Two implementation options, choose and use according to personal preference

Nginx Reverse Proxy for Telegram Api#

Install nginx#

sudo apt update && sudo apt install -y nginx

Create configuration file#

nano tgapi.conf

Enter the following content and save

server {
    listen 80;
    server_name tgapi.domain;
    location / {
       return 444;
    }
    location ~* ^/bot {
        resolver 8.8.8.8;
        proxy_buffering off;
        proxy_pass      https://api.telegram.org$request_uri;
    }
}

Load configuration#

sudo systemctl reload nginx
#or
sudo nginx -s reload

Test access#

Enter the following command line, replacing BOT_TOKEN with your own bot token.

curl https://tgapi.domain/bot<BOT_TOKEN>/getMe

If you see the bot information, it means it is working.

Configure epusdt telegram proxy url#

epusdt configuration (.env) reference

#telegram proxy url (for mainland servers, a foreign server can be used as a reverse proxy for tg), if running on a foreign server, no need to fill in
tg_proxy=https://tgapi.domain

Docker configuration nginx reference docker-compose.yaml content#

version: "3"
services:
  nginx:
    container_name: "nginx"
    restart: always
    ports:
      - "80:80"
    image: nginx:bookworm
    volumes:
      - ./conf.d:/etc/nginx/conf.d
      - ./log:/var/log/nginx
    extra_hosts:
      - "host.docker.internal:host-gateway"

Use Cloudflare Worker to Proxy Telegram Bot Api#

Prerequisites

  1. A domain hosted on Cloudflare
  2. Enable Cloudflare's free worker service

First, log in to Cloudflare and click Workers and Pages on the left side#

Click Create Application-Create Worker

Fill in a Name, click Deploy

After creation, click on the newly created Worker, then click Quick Edit

Delete the existing code on the left side and enter the code provided below

/**
 * Helper functions to check if the request uses
 * corresponding method.
 *
 */
const Method = (method) => (req) => req.method.toLowerCase() === method.toLowerCase();
const Get = Method('get');
const Post = Method('post');

const Path = (regExp) => (req) => {
	const url = new URL(req.url);
	const path = url.pathname;
	return path.match(regExp) && path.match(regExp)[0] === path;
};

/*
 * The regex to get the bot_token and api_method from request URL
 * as the first and second backreference respectively.
 */
const URL_PATH_REGEX = /^\/bot(?<bot_token>[^/]+)\/(?<api_method>[a-z]+)/i;

/**
 * Router handles the logic of what handler is matched given conditions
 * for each request
 */
class Router {
	constructor() {
		this.routes = [];
	}

	handle(conditions, handler) {
		this.routes.push({
			conditions,
			handler,
		});
		return this;
	}

	get(url, handler) {
		return this.handle([Get, Path(url)], handler);
	}

	post(url, handler) {
		return this.handle([Post, Path(url)], handler);
	}

	all(handler) {
		return this.handler([], handler);
	}

	route(req) {
		const route = this.resolve(req);

		if (route) {
			return route.handler(req);
		}

		const description = 'No matching route found';
		const error_code = 404;

		return new Response(
			JSON.stringify({
				ok: false,
				error_code,
				description,
			}),
			{
				status: error_code,
				statusText: description,
				headers: {
					'content-type': 'application/json',
				},
			}
		);
	}

	/**
	 * It returns the matching route that returns true
	 * for all the conditions if any.
	 */
	resolve(req) {
		return this.routes.find((r) => {
			if (!r.conditions || (Array.isArray(r) && !r.conditions.length)) {
				return true;
			}

			if (typeof r.conditions === 'function') {
				return r.conditions(req);
			}

			return r.conditions.every((c) => c(req));
		});
	}
}

/**
 * Sends a POST request with JSON data to Telegram Bot API
 * and reads in the response body.
 * @param {Request} request the incoming request
 */
async function handler(request) {
	// Extract the URl method from the request.
	const { url, ..._request } = request;

	const { pathname: path, search } = new URL(url);

	// Leave the first match as we are interested only in backreferences.
	const { bot_token, api_method } = path.match(URL_PATH_REGEX).groups;

	// Build the URL
	const api_url = 'https://api.telegram.org/bot' + bot_token + '/' + api_method + search;

	// Get the response from API.
	const response = await fetch(api_url, _request);

	const result = await response.text();

	const res = new Response(result, _request);

	res.headers.set('Content-Type', 'application/json');

	return res;
}

/**
 * Handles the incoming request.
 * @param {Request} request the incoming request.
 */
async function handleRequest(request) {
	const r = new Router();
	r.get(URL_PATH_REGEX, (req) => handler(req));
	r.post(URL_PATH_REGEX, (req) => handler(req));

	const resp = await r.route(request);
	return resp;
}

/**
 * Hook into the fetch event.
 */
addEventListener('fetch', (event) => {
	event.respondWith(handleRequest(event.request));
});

Save and Deploy

Go back to the management dashboard homepage, click Website on the left side, and click Your domain hosted on Cloudflare on the right side

Select Workers Routes for the domain

Select Add Route

Fill in Route with the subdomain you want to use, for example: tgapi.domain/* Note that it must end with /*, select the Worker service you just created, and click Save.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.