rendrom / rosreestr2coord

Вычисление координат участка по кадастровому номеру с сайта https://pkk.rosreestr.ru
MIT License
167 stars 79 forks source link

Ошибки сертификата при попытке получить данные #87

Closed YungIshimura closed 1 month ago

YungIshimura commented 1 month ago

Добрый день. При попытке получения данных получаю ошибку. image

Прокси не помогает. image

albinail commented 1 month ago

Добрый день, аналогично "Start downloading area info: https://pkk.rosreestr.ru/api/features/1/38:6:144003:4723 [SSL: TLSV1_ALERT_DECODE_ERROR] tlsv1 alert decode error (_ssl.c:1007)" p.s. у вас оч полезная библиотека, спасибо

albinail commented 1 month ago

image в колабе: Start downloading area info: https://pkk.rosreestr.ru/api/features/1/38:6:144003:4723 ERROR:rosreestr2coord.logger:Request failed: timed out

RomanBespalov commented 1 month ago

Добрый день. При попытке получения данных получаю ошибку. image

Прокси не помогает. image

Привет, здесь написал, как решил - https://github.com/rendrom/rosreestr2coord/issues/72#issuecomment-2362843205

andponom commented 1 month ago

Опытным путём выяснили, что запросы продолжают исполняться в среде 3.9 и ранее. Начиная с 3.10 лезет эта ошибка.

rendrom commented 1 month ago

Добрый день. При попытке получения данных получаю ошибку. image Прокси не помогает. image

Привет, здесь написал, как решил - #72 (comment)

@RomanBespalov спасибо за решение. Выпустил новую версию с переделанной системой запросов. Но флаг -P пока не удалось вернуть. Нужно искать другие варианты проксирования.

skemaikin commented 1 month ago

Доброго времени! Есть еще один способ решения проблемы. Правда, он связан с использованием сертификата. Для файла utils.py в методе perform_request следует использовать контекст:

context = ssl.create_default_context()
context.set_ciphers('DEFAULT@SECLEVEL=1')
context.minimum_version = ssl.TLSVersion.TLSv1_2
context.load_verify_locations('cacert.pem')

Сертификаты можно скачать, например, отсюда: https://www.gosuslugi.ru/crt

rendrom commented 1 month ago

Доброго времени! Есть еще один способ решения проблемы. Правда, он связан с использованием сертификата. Для файла utils.py в методе perform_request следует использовать контекст:

context = ssl.create_default_context()
context.set_ciphers('DEFAULT@SECLEVEL=1')
context.minimum_version = ssl.TLSVersion.TLSv1_2
context.load_verify_locations('cacert.pem')

Сертификаты можно скачать, например, отсюда: https://www.gosuslugi.ru/crt

Но это всё равно не решит проблемы с блокировкой по IP при превышении лимитов запросов.

skemaikin commented 1 month ago

Доброго времени! Есть еще один способ решения проблемы. Правда, он связан с использованием сертификата. Для файла utils.py в методе perform_request следует использовать контекст:

context = ssl.create_default_context()
context.set_ciphers('DEFAULT@SECLEVEL=1')
context.minimum_version = ssl.TLSVersion.TLSv1_2
context.load_verify_locations('cacert.pem')

Сертификаты можно скачать, например, отсюда: https://www.gosuslugi.ru/crt

Но это всё равно не решит проблемы с блокировкой по IP при превышении лимитов запросов.

В режиме проксёвой рулетки (перебор прокси-списка) - вроде решает. В utils.py:

def get_rosreestr_headers() -> Dict[str, str]:
    from fake_useragent import UserAgent
    return {
        "pragma": "no-cache",
        "referer": "https://pkk.rosreestr.ru/",
        "user-agent": UserAgent().random,
        "x-requested-with": "XMLHttpRequest",
    }

def perform_request(
    url: str,
    proxy_handler: Optional[urllib.request.ProxyHandler],
    logger: Optional[object],
    timeout: int,
) -> bytes:
    try:
        headers = get_rosreestr_headers()
        if proxy_handler:
            opener = urllib.request.build_opener(proxy_handler)
            urllib.request.install_opener(opener)
        request = Request(url, headers=headers)

        context = ssl.create_default_context()
        context.set_ciphers('DEFAULT@SECLEVEL=1')
        context.minimum_version = ssl.TLSVersion.TLSv1_2
        context.load_verify_locations('cacert.pem')

        with urlopen(request, context=context, timeout=timeout) as response:
            read = response.read()
        is_error = is_error_response(url, read)
        if is_error:
            raise Exception(is_error)
        return read
    except urllib.error.HTTPError as er:
        if er.code == 400:
            raise er
        else:
            raise Exception(f"HTTPError: {er}")
    except Exception as er:
        if logger:
            logger.error(f"Request failed: {er}")
        raise
zdch26 commented 1 month ago

Доброго времени! Есть еще один способ решения проблемы. Правда, он связан с использованием сертификата. Для файла utils.py в методе perform_request следует использовать контекст:

context = ssl.create_default_context()
context.set_ciphers('DEFAULT@SECLEVEL=1')
context.minimum_version = ssl.TLSVersion.TLSv1_2
context.load_verify_locations('cacert.pem')

Сертификаты можно скачать, например, отсюда: https://www.gosuslugi.ru/crt

Похоже там проблема не столько в сертификате, сколько в поддержке набора шифров на стороне pkk.rosreestr.ru С их стороны при TLS рукопожатии согласуется TLS_RSA_WITH_AES_256_CBC_SHA (возможно, и другие, но сути не поменяет), а он в актуальных сборках TLS библиотек не поддерживается, потому что уже считается слабым (https://ciphersuite.info/cs/TLS_RSA_WITH_AES_256_CBC_SHA/). Поэтому когда сервер pkk.rosreestr.ru в Client Hello их не находит, то сразу рвёт соединение (decord error).

В принципе, в utils.py должно быть достаточно одной строки, чтобы заработало context.set_ciphers('ALL:@SECLEVEL=1')

Screen Shot 2024-09-24 at 18 13 06

skemaikin commented 1 month ago

Похоже там проблема не столько в сертификате, сколько в поддержке набора шифров на стороне pkk.rosreestr.ru С их стороны при TLS рукопожатии согласуется TLS_RSA_WITH_AES_256_CBC_SHA (возможно, и другие, но сути не поменяет), а он в актуальных сборках TLS библиотек не поддерживается, потому что уже считается слабым (https://ciphersuite.info/cs/TLS_RSA_WITH_AES_256_CBC_SHA/). Поэтому когда сервер pkk.rosreestr.ru в Client Hello их не находит, то сразу рвёт соединение (decord error).

Недавно от одного из наших клиентов прилетело требование отключить поддержку устаревших криптографических протоколов TLS1.0 и TLS1.1. Судя по всему, это разнарядка со стороны госструктур, нужно работать с более свежими версиями TLS.

В принципе, в utils.py должно быть достаточно одной строки, чтобы заработало context.set_ciphers('ALL:@SECLEVEL=1')

Увы, не работает. Говорит: SSL: CERTIFICATE_VERIFY_FAILED.

zdch26 commented 1 month ago

pkk.rosreestr.ru работает с TLS 1.2, но вот сами алгоритмы шифрования почему-то используются устаревшие. По поводу ошибки сертификата - подразумеваю, ему корневых не хватает на стороне клиента или игнорирования того, что он самоподписанный. Так работало:

context = ssl._create_unverified_context()
context.set_ciphers('ALL:@SECLEVEL=1')
skemaikin commented 1 month ago
context = ssl._create_unverified_context()
context.set_ciphers('ALL:@SECLEVEL=1')

Точно так, работает!

rendrom commented 1 month ago

Всем спасибо за обсуждение и поиск способов исправления! Выпустил новую версию с ещё одной переработкой по этой проблеме.