Ошибка проверки сертификата SSLError python telebot при подключении через proxy
Работаю через корпоративную сеть, есть потребность написать телеграмм бота, пробовал различные библиотеки (telebot, telepot, telegram, airogram). Везде сталкиваюсь с проблемой доступа через корпоративный прокси. Сейчас остановился на telebot, подсунул прокси, теперь ошибка с проверкой сертификата.
Пробовал использовать http, https, socks5, socks5h, socks4 успеха не принесло.
import telebot
import json
from telebot import apihelper
with open('params.json', 'r', encoding='utf-8') as f:
data = json.load(f)
username = data['username']
password = data['password']
access_token_tg = data['access_token_tg']
bot = telebot.TeleBot(access_token_tg)
apihelper.proxy = {'https': f'https://{username}:{password}@10.0.18.139:3131'}
print(bot.get_me())
Получаю в ответ ошибку.
requests.exceptions.SSLError: HTTPSConnectionPool(host='api.telegram.org', port=443): Max retries exceeded with url: /мой токен тут/getMe (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1123)')))
Попробовал общаться через request с телегой, удалось подключиться, только после отключения проверки ssl session.verify = False. Но через запросы очень проблематично писать, собственно и библиотек для этого куча есть.
import pprint
from requests.auth import HTTPProxyAuth
import urllib3
import requests
import json
# читаем конфиг
with open('params.json', 'r', encoding='utf-8') as f:
data = json.load(f)
username = data['username']
password = data['password']
access_token_tg = data['access_token_tg']
# создаем сессию для работы с ботом
auth = HTTPProxyAuth(username, password)
proxies = {'https': f'https://{username}:{password}@10.0.18.139:3131'}
session = requests.Session()
session.proxies = proxies
session.auth = auth
# отрубили проверку сертификата и варнинга
urllib3.disable_warnings()
session.verify = False
MAIN_URL = f'https://api.telegram.org/bot{access_token_tg}'
res = session.post(f'{MAIN_URL}/getMe').json()
pprint.pprint(res)```
Таким образом работает.
Прошу помочь разобраться или может мануал или библу другую посоветовать, 2 неделю бьюсь с этим.
Ответы (2 шт):
Попробуйте напрямую модифицировать библиотеку для работы с API телеграмма.
Если вы устанавливали библиотеку напрямую в python, то она находится в следующей директории:
Python{версия}/Lib/site-packages/{имя_библиотеки}
Если в виртуальном окружении работаете, то она находится в:
{имя_виртуального_окружения}/Lib/site-packages/{имя_библиотеки}
Находите модуль отвечающий за запросы, в большинстве библиотек для взаимодействия с API его проектируют так, что запросы выполняются в одной функции, её и надо модифицировать. На примере я показываю pyTelegramBotAPI, функция _make_request лежит в ../Lib/site-packages/telebot/apihelper.py и выглядит так (код частично срезан чтобы выделить главные детали):
def _make_request(token, method_name, method='get', params=None, files=None):
if API_URL:
request_url = API_URL.format(token, method_name)
else:
request_url = "https://api.telegram.org/bot{0}/{1}".format(token, method_name)
read_timeout = READ_TIMEOUT
connect_timeout = CONNECT_TIMEOUT
#...
if RETRY_ON_ERROR:
got_result = False
current_try = 0
while not got_result and current_try<MAX_RETRIES-1:
current_try+=1
try:
result = _get_req_session().request(
method, request_url, params=params, files=files,
timeout=(connect_timeout, read_timeout), proxies=proxy)
got_result = True
except HTTPError:
#...
if not got_result:
result = _get_req_session().request(
method, request_url, params=params, files=files,
timeout=(connect_timeout, read_timeout), proxies=proxy)
else:
result = _get_req_session().request(
method, request_url, params=params, files=files,
timeout=(connect_timeout, read_timeout), proxies=proxy)
#...
json_result = _check_result(method_name, result)
if json_result:
return json_result['result']
В pyTelegramBotAPI _get_req_session() возвращает объект requests.Session(), а значит чтобы убрать сертификат или добавить свой, здесь хватит модифицировать строки с отправкой запроса (в примере кода отключается проверка сертификата):
result = _get_req_session().request(
method, request_url, params=params, files=files,
timeout=(connect_timeout, read_timeout), proxies=proxy, verify=False)
Если библиотека асинхронная, там используется aiohttp, как там работать с сертификатами описано в документации. Я привёл пример только с одной синхронной библиотекой, но во всех +- принцип решения данной проблемы такой же.
Добавлю к ответу @Georgiy а чтобы не спамило предупреждениями о небезопасности, в том же модуле добавить:
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)