Проблемы в SSL при запуске Telegram бота

Всем привет! Написал бота для Telegram и хотел запустить его на сервере. Бот написан на telebot и concurrent.futures. По команде, он парсит сайт и отправляет данные парсинга в ответ пользователю. На Windows все прекрасно работает. На сервере нет. Я использую VDS сервер на Ubuntu 22.04. Для скрипта vevn настроил, запуск настроил, НО... У меня выдает ошибку при обращении в tg.

urllib3.exceptions.SSLError: [SSL: D
ECRYPTION_FAILED_OR_BAD_RECORD_MAC] decryption failed or bad record mac (_ssl.c:
2578)

Я получил сертификат через certbot. Для проверки выполнил код:

import ssl
import requests

cert_path = "/etc/letsencrypt/live/*********.duckdns.org"
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(certfile=f"{cert_path}/fullchain.pem", keyfile=f"{cert_path}/privkey.pem")
url = "https://example.com"

try:
    response = requests.get(url, verify=True, timeout=5, cert=(f"{cert_path}/fullchain.pem", f"{cert_path}/privkey.pem"))
    print(response.text)
except requests.exceptions.RequestException as e:
    print(f"Error: {e}")

Получил:

<html>
<head>
    <title>Example Domain</title>
    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
    }
    div {
        width: 600px;
        margin: 5em auto;
        padding: 2em;
        background-color: #fdfdff;
        border-radius: 0.5em;
        box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
    }
    a:link, a:visited {
        color: #38488f;
        text-decoration: none;
    }
    @media (max-width: 700px) {
        div {
            margin: 0 auto;
            width: auto;
        }
    }
    </style>
</head>
<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is for use in illustrative examples in documents. You may use this
    domain in literature without prior coordination or asking for permission.</p>
    <p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>

Получается все ок, сайт парситься будет. Но при выполнении этого:

import ssl
import requests

cert_path = "/etc/letsencrypt/live/*************.duckdns.org"
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(certfile=f"{cert_path}/fullchain.pem", keyfile=f"{cert_path}/privkey.pem")
telegram_url = "https://api.telegram.org/bot<TOKEN>/getMe"

try:
    response = requests.get(telegram_url, verify=True, timeout=5, cert=(f"{cert_path}/fullchain.pem", f"{cert_path}/privkey.pem"))
    print(response.text)
except requests.exceptions.RequestException as e:
    print(f"Error: {e}")

Получется это:


{'ok': False, 'error_code': 404, 'description': 'Not Found'}


Ответы (1 шт):

Автор решения: DeNRuDi

Не совсем понятно, для чего вам использовать сертификаты именно для запроса к Telegram с VDS, но допустим что вам по какой-то причине это понадобилось.

Есть несколько нюансов из вашего вопроса:

  1. Убедитесь, что вы верно сгенерировали сертификаты. Как простой вариант проверки - поднимите какой-нибудь тестовый сервер на VDS, например на gunicorn или uvicorn и проверьте свои сертификаты.

Простенький пример

# pip3 install uvicorn fastapi
from fastapi import FastAPI
import uvicorn

app = FastAPI()


@app.get('/')
async def index():
    return {'result': 200}

if __name__ == '__main__':
    cert_path = "/etc/letsencrypt/live/*********.duckdns.org"
    uvicorn.run(
        app=app,
        ssl_keyfile=f"{cert_path}/fullchain.pem",
        ssl_certfile=f"{cert_path}/privkey.pem",
        host='0.0.0.0',  # <- или ваш ip vds сервера
        port=5000
    )

Постучитесь на свой сокет https://ваш_ip:5000 через браузер и посмотрите, что у вас валидные сертификаты.

  1. Как бы странно это не звучало, но если бы вы настроили неверно сертификаты - вы бы уже на уровне запроса с ssl и handshake-ом получили ошибку при запросе к Telegram, но вы получаете {'ok': False, 'error_code': 404, 'description': 'Not Found'}, это судя по всему не связано с сертификатами, а из-за невалидного запроса к серверу. Сертификаты к Telegram чаще всего нужны тогда, когда вы настраиваете webhook, но вряд ли у вас в коде это есть.

А проблема в том, что здесь вы забыли указать реальный токен бота, потому что если реально сделать запрос на этот url https://api.telegram.org/bot<TOKEN>/getMe, то вы реально получите 404. Реальная ссылка будет выглядеть вот так:

https://api.telegram.org/bot123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11/getMe

Только замените на свой токен, который нужно получить у BotFather.

→ Ссылка