Проблемы в 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 шт):
Не совсем понятно, для чего вам использовать сертификаты именно для запроса к Telegram с VDS, но допустим что вам по какой-то причине это понадобилось.
Есть несколько нюансов из вашего вопроса:
- Убедитесь, что вы верно сгенерировали сертификаты. Как простой вариант проверки - поднимите какой-нибудь тестовый сервер на
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 через браузер и посмотрите, что у вас валидные сертификаты.
- Как бы странно это не звучало, но если бы вы настроили неверно сертификаты - вы бы уже на уровне запроса с
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.