Eu li os documentos e não consigo encontrar uma referência para desativar a verificação de certificado SSL. No momento, tenho um projeto em que estou fazendo um ataque man-in-the-middle intencional para alternar proxies conforme a necessidade.
client <-> Proxy Switcher (server acting as proxy)
Proxy Switcher (emulated client) <-> Exchanges
No retorno de qualquer coisa que não seja 200
, o alternador de proxy muda automaticamente o proxy e tenta novamente. Um man-in-the-middle é necessário para verificar se as solicitações HTTPS estão voltando com os cabeçalhos adequados, e essa parte parece funcionar bem. No entanto, a comunicação entre o cliente e o alternador de proxy parece estar retornando os problemas de certificado SSL (esperados), pois o alternador de proxy gera automaticamente seu próprio certificado local. Eu gostaria de desativar isso.
Sem adicionar o certificado ao meu ambiente confiável local, recebo o erro:
(Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')])")))
O que é garantido, mas seria melhor se pudesse ser desativado por alguma bandeira de troca. Ao adicionar o certificado ao meu ambiente confiável local, recebo o erro
(Caused by SSLError(SSLCertVerificationError("hostname 'pro.coinbase.com' doesn't match 'Felipes-MacBook-Pro.local'")))
O que também é garantido, mas um cheque que prefiro desativar. Qualquer ajuda seria apreciada. Minha ideia seria algo simples como:
ex = getattr(ccxt, exchange)(
{
"session": cfscrape.create_scraper(),
"enableRateLimit": False,
"verify_ssl_certificates": False,
}
)
Observação: tentei o sinalizador verify
sem sucesso.
@synchronizing
@synchronizing ↓ isso ajuda?
session = cfscrape.create_scraper()
session.verify = False
ex = getattr(ccxt, exchange)(
{
"session": session,
"enableRateLimit": False,
}
)
@synchronizing
- Qual é a sua versão do Python?
- Você está usando a versão sincronizada ou assíncrona do lib?
Python 3.7.2 e usando sincronização (testado com cfscrape e sem). Também tentarei assíncrono, só para ter certeza, pois sei que aiohttp
tem menos verificações SSL.
@synchronizing, deixe-nos saber se o comentário acima não resolver o problema para você: https://github.com/ccxt/ccxt/issues/5394#issuecomment -506918563
@synchronizing ↓ isso ajuda?
session = cfscrape.create_scraper() session.verify = False ex = getattr(ccxt, exchange)( { "session": session, "enableRateLimit": False, } )
Testado com o acima com o mesmo erro de verificação SSL, infelizmente.
Testado com ccxt_async
, e parece funcionar bem - passa pelo localizador de proxy também, sem apresentar nenhum problema. SSL certificado adicionado em env (não tenho certeza se funcionaria sem.)
No entanto, cfscrape
ainda é desejado para coinbasepro.
Esta página informa que deveria ter funcionado com a versão de sincronização também: https://2.python-requests.org/en/master/user/advanced/#ssl -cert-verification
@synchronizing você pode postar um pequeno trecho completo de seu código para reproduzi-lo, digamos, 10-20 linhas? Precisamos ter certeza de que não há outra interferência, portanto, precisamos de um trecho completo, incluindo a instanciação.
Com certeza, @kroitor - a partir de agora o código está empacotado em um servidor de API, então me dê alguns para extrair as linhas relevantes para um arquivo de texto separado para facilitar o teste do seu lado.
Além disso: session.verify
um booleano ou uma string de localização de certificado? Pelas edições anteriores que vi aqui, pensei que era simplesmente um sinalizador bool.
Além disso: session.verify é um booleano ou uma string de localização de certificado? Pelas edições anteriores que vi aqui, pensei que era simplesmente um sinalizador bool.
Deve funcionar de qualquer maneira, como um booleano ou como um caminho de string, se os documentos estiverem corretos.
Além disso: session.verify é um booleano ou uma string de localização de certificado? Pelas edições anteriores que vi aqui, pensei que era simplesmente um sinalizador bool.
Deve funcionar de qualquer maneira, como um booleano ou como um caminho de string, se os documentos estiverem corretos.
Parece bom. Dê-me alguns para compilar o problema em algumas linhas de código.
Utilizando o seguinte código:
import ccxt
exchange = ccxt.binance()
exchange.session.verify = False # With, or without line.
fetch = exchange.fetch_ohlcv("ETH/BTC", "1m", 1514764800000)
print(fetch)
Com a exportação para um proxy man-in-the-middle:
export http_proxy=http://127.0.0.1:8888
export https_proxy=http://127.0.0.1:8888
Ainda recebo erros na versão de sincronização de ccxt
. Se quiser testá-lo com o man-in-the-middle, você pode encontrá-lo em meu repositório aqui . Basta executar o arquivo example/example_server.py
.
Acabei de perceber que o motivo pelo qual pode ter funcionado com aiohttp
é que mesmo com a configuração exchange.session.trust_env
e exchange.session.trust_env_aiohttp
, nenhuma das bandeiras respeita o conjunto http_proxy
e https_proxy
env variável.
Atualização: aiohttp
também não funciona.
async def fetch_stuff():
exchange = ccxt.binance({"aiohttp_proxy": "http://127.0.0.1:8888", "verify": False})
fetch = await exchange.fetch_ohlcv("ETH/BTC", "1m", 1514764800000)
await exchange.close()
return fetch
print(asyncio.get_event_loop().run_until_complete(asyncio.gather(fetch_stuff())))
Com aiohttp_proxy
definido implícito (uma vez que http_proxy
e https_proxy
não parecem ser respeitados), as verificações SSL ainda retornam erro. Eu sei que aiohttp
usa o sinalizador ssl
(em vez de verify
, como a biblioteca requests
, para ativar / desativar as verificações SSL), mas presumo não há bandeira existente para ccxt
.
async def fetch_stuff():
exchange = ccxt.binance({"aiohttp_proxy": "http://127.0.0.1:8888", "verify": False})
fetch = await exchange.fetch_ohlcv("ETH/BTC", "1m", 1514764800000)
await exchange.close()
return fetch
↑ Esta não é uma maneira correta de configurá-lo. Você deve adicionar uma sessão assíncrona e definir verify = False
nela, antes de passá-la para o construtor binance. A classe de troca derivada não suporta a opção verify
.
Mais sobre isso aqui:
O mau comportamento de sincronização pode ser um bug no proxy MITM: https://www.google.com/search?q=python+https+proxy+ssl+verify+requests. Parece que você não é a única pessoa com dificuldades ao usar proxies + verificação SSL.
async def fetch_stuff(): exchange = ccxt.binance({"aiohttp_proxy": "http://127.0.0.1:8888", "verify": False}) fetch = await exchange.fetch_ohlcv("ETH/BTC", "1m", 1514764800000) await exchange.close() return fetch
↑ Esta não é uma maneira correta de configurá-lo. Você deve adicionar uma sessão assíncrona e definir
verify = False
nela, antes de passá-la para o construtor binance. A classe de troca derivada não suporta a opçãoverify
.
Quando você diz isso, este seria o formato correto?
async def fetch_stuff():
exchange = ccxt.binance({"aiohttp_proxy": "http://127.0.0.1:8888"})
exchange.session.verify = False
fetch = await exchange.fetch_ohlcv("ETH/BTC", "1m", 1514764800000)
await exchange.close()
return fetch
print(asyncio.get_event_loop().run_until_complete(asyncio.gather(fetch_stuff())))
Pode ser um bug no proxy MITM: https://www.google.com/search?q=python+https+proxy+ssl+verify+requests. Parece que você não é a única pessoa com dificuldades ao usar proxies + verificação SSL.
Conte-me sobre isso - os proxies SLL + são um pesadelo, como descobri 😩. No entanto, mitm
está agindo como o servidor de destino para o cliente, portanto, não está realmente comunicando a solicitação de encaminhamento ao servidor de destino como faria um proxy normal. Em vez disso, ele inicia um cliente emulado que faz isso e, em seguida, retorna a solicitação do cliente emulado para o cliente real, lendo a solicitação no meio. O problema é a comunicação inicial entre mitm
e o cliente com ccxt
, principalmente devido a um certificado autoassinado no meio. Mesmo com o sinalizador verify
definido como falso, o erro parece persistir.
seria este o formato correto?
Não. Este seria o formato correto:
import aiohttp
import asyncio
event_loop = asyncio.get_event_loop()
async def fetch_stuff():
connector = aiohttp.TCPConnector(ssl=False, loop=event_loop)
session = aiohttp.ClientSession(loop=event_loop, connector=connector, trust_env=True)
exchange = ccxt.binance({"aiohttp_proxy": "http://127.0.0.1:8888", 'session': session})
fetch = await exchange.fetch_ohlcv("ETH/BTC", "1m", 1514764800000)
await exchange.close()
return fetch
print(event_loop.run_until_complete(asyncio.gather(fetch_stuff())))
Isso ajuda?
seria este o formato correto?
Não. Este seria o formato correto:
import aiohttp import asyncio event_loop = asyncio.get_event_loop() async def fetch_stuff(): trust_environment_variables = False connector = aiohttp.TCPConnector(ssl=False, loop=event_loop) session = aiohttp.ClientSession(loop=event_loop, connector=connector, trust_env=trust_environment_variables) exchange = ccxt.binance({"aiohttp_proxy": "http://127.0.0.1:8888", 'session': session}) fetch = await exchange.fetch_ohlcv("ETH/BTC", "1m", 1514764800000) await exchange.close() return fetch print(event_loop.run_until_complete(asyncio.gather(fetch_stuff())))
Isso ajuda?
Sim, é verdade! Recebi uma solicitação no mitm
que foi processada, mas não foi devolvida corretamente (que é falha de mitm
). Muito apreciado homem! Deixe-me tentar com a sincronização ccxt
.
@synchronizing algo como o acima deve funcionar para a versão sync
também. Só preciso cavar a internet sobre a maneira adequada de configurá-lo. No entanto, isso está além do CCXT, infelizmente.
@synchronizing algo como o acima deve funcionar para a versão
sync
também. Só preciso cavar a internet sobre a maneira adequada de configurá-lo. No entanto, isso está além do CCXT, infelizmente.
Perfeitamente compreensível - tudo que eu esperava era um CONNECT
adequado e GET
com mitm
, pois dali em diante eu sabia que ccxt
tinha completado o correto etapas SSL.
@synchronizing, tudo bem se fecharmos isso agora?
Perdoe-me pelo questionamento repetitivo: mas com cfscraper
e a funcionalidade de sincronização padrão, podemos definir um session
? Enquanto eu tenho você na escuta.
Se isso estiver além do projeto devido a cfscraper
, não se preocupe. A ajuda acima já foi fantástica e eu realmente aprecio isso.
Além disso, completamente irrelevante: não caia em AdBlocker Pro
- eles foram comprados por alguma empresa há algum tempo e ainda exibem anúncios. A solução de código aberto é o uBlock Origin, que muito poucas pessoas parecem saber que existe e também é um excelente bloqueador em comparação (incluindo anúncio no YouTube, graças a Deus).
Perdoe-me pelo questionamento repetitivo: mas com cfscraper e funcionalidade de sincronização padrão, podemos definir uma sessão?
Sim, isso deveria ser possível. No entanto, pode haver bugs fora do CCXT:
Em breve adicionarei a opção exchange.verify
para a versão sync
e precisarei de sua ajuda para testá-la em seu proxy.
Perdoe-me pelo questionamento repetitivo: mas com cfscraper e funcionalidade de sincronização padrão, podemos definir uma sessão?
Sim, isso deveria ser possível. No entanto, pode haver bugs fora do CCXT:
Em breve adicionarei a opção
exchange.verify
para a versãosync
e precisarei de sua ajuda para testá-la em seu proxy.
Soa como um plano! Mais uma vez, agradeço a ajuda. Sinta-se à vontade para fechar este problema e reabri-lo quando for necessário para o teste.
@synchronizing não deve demorar muito,
@synchronizing não deve demorar muito,
Parece bom para mim, estarei aqui.
Ok, aqui está o que precisamos fazer:
# sync
import ccxt
exchange = ccxt.binance({'verify': False})
fetch = exchange.fetch_ohlcv("ETH/BTC", "1m", 1514764800000)
print(fetch)
ou
# async
async def fetch_stuff():
exchange = ccxt.binance({"aiohttp_proxy": "http://127.0.0.1:8888", "verify": False})
fetch = await exchange.fetch_ohlcv("ETH/BTC", "1m", 1514764800000)
await exchange.close()
return fetch
Ficaremos felizes se você nos informar se isso resolveu o problema para você ou não.
Ficaremos felizes se você nos informar se isso resolveu o problema para você ou não.
Ofc, ficaremos felizes em ajudar. Para o async
, recurso pretendido para atribuir verify
diretamente no construtor binance
?
Para o assíncrono, o recurso pretendido para atribuição de verificação diretamente no construtor binance?
Sim, adicionei a opção de construtor verify
às versões sync
e async
. Você também pode defini-lo depois de criar a instância de troca:
exchange = ccxt.binance()
exchange.verify = False
Para o assíncrono, o recurso pretendido para atribuição de verificação diretamente no construtor binance?
Sim, adicionei a opção
verify
às versõessync
easync
.
Bonito. Vou dar uma chance agora.
@synchronizing encontrou alguns pequenos problemas ao longo do caminho, adicionou as correções, portanto, chegará em breve (5-10 minutos). Em espera.
@synchronizing encontrou alguns pequenos problemas ao longo do caminho, adicionou as correções, portanto, chegará em breve (5-10 minutos). Em espera.
Qual versão devo procurar?
@synchronizing 1.18.844 (o que
Ok, chegou, ansioso por ouvir de você.
sync
versão está funcionando como esperado em 1.18.844
:
import ccxt as ccxt
exchange = ccxt.binance(
{
"proxies": {"http": "http://127.0.0.1:8888", "https": "http://127.0.0.1:8888"},
"verify": False,
}
)
fetch = exchange.fetch_ohlcv("ETH/BTC", "1m", 1514764800000)
print(fetch)
async
version não funciona com o seguinte:
import ccxt.async_support as ccxt
import asyncio
async def fetch_stuff():
exchange = ccxt.binance({"aiohttp_proxy": "http://127.0.0.1:8888", "verify": False})
fetch = await exchange.fetch_ohlcv("ETH/BTC", "1m", 1514764800000)
await exchange.close()
return fetch
print(asyncio.get_event_loop().run_until_complete(asyncio.gather(fetch_stuff())))
O erro SSL é lançado para o código acima. No entanto, ela não funciona durante o carregamento session
, como mostrado anteriormente aqui . Presumivelmente, verify
pode não estar configurando a bandeira ssl
em TCPConnector
para False
internamente dentro de ccxt
.
Supostamente, a verificação pode não estar definindo o sinalizador ssl no TCPConnector como False internamente no ccxt.
Ok, adicionei mais uma edição a ele, informe-nos se 1.18.845 não resolver o problema do lado async
. Fechando isso por enquanto. Sinta-se à vontade para reabri-lo ou apenas fazer mais perguntas, se houver. Ficaremos felizes se você relatar de qualquer maneira.
Parece bom - vou fazer uma tentativa, obrigado novamente.
async
ainda não está trabalhando com 1.18.845
com "verify" : False
definido.
import ccxt.async_support as ccxt
import asyncio
async def fetch_stuff():
exchange = ccxt.binance({"aiohttp_proxy": "http://127.0.0.1:8888", "verify": False})
print(exchange.verify)
fetch = await exchange.fetch_ohlcv("ETH/BTC", "1m", 1514764800000)
await exchange.close()
return fetch
print(asyncio.get_event_loop().run_until_complete(asyncio.gather(fetch_stuff())))
@synchronizing não funciona com verify: False
, mas funciona com https://github.com/ccxt/ccxt/issues/5394#issuecomment -506921151?
@synchronizing não funciona com
verify: False
, mas funciona com # 5394 (comentário) ?
Correto, infelizmente.
@synchronizing, você tem certeza disso? Isso é estranho, porque eles deveriam ser tecnicamente iguais ...
@synchronizing ah, nvm, encontrei outro bug ali com a ordem das chamadas, vai consertar em um momento.
@synchronizing, você tem certeza disso? Isso é estranho, porque eles deveriam ser tecnicamente iguais ...
Eles parecem ser diferentes em mais testes:
import ccxt.async_support as ccxt
import asyncio
import aiohttp
async def fetch_stuff():
connector = aiohttp.TCPConnector(ssl=False, loop=asyncio.get_event_loop())
exchange = ccxt.binance({"aiohttp_proxy": "http://127.0.0.1:8888", "verify": False})
print(exchange.session._connector._ssl)
print(connector._ssl)
await exchange.close()
asyncio.get_event_loop().run_until_complete(fetch_stuff())
Saídas:
<ssl.SSLContext object at 0x10f55c480>
False
@synchronizing ah, nvm, encontrei outro bug ali com a ordem das chamadas, vai consertar em um momento.
Incrível, lmk!
@synchronizing ok, vamos tentar novamente com 1.18.846. Infelizmente, não posso realmente testá-lo do meu lado, atm, sua ajuda com a depuração é muito apreciada! A autoconstrução leva de 10 a 15 minutos.
@synchronizing ok, vamos tentar novamente com 1.18.846. Infelizmente, não posso realmente testá-lo do meu lado, atm, sua ajuda com a depuração é muito apreciada! A autoconstrução leva de 10 a 15 minutos.
Meu prazer homem - eu agradeço todo o trabalho em sua extremidade Estarei atento ao novo lançamento para fazer uma tentativa.
Funcionando como esperado! Obrigado novamente, felicidades.
@kroitor
Devemos registrar um aviso se os certificados SSL forem desativados ou substituídos, já que isso pode resultar em chaves roubadas? Ataque MITM e há algumas trocas usando dados de login como chaves (por exemplo, dx.exchange).
@kroitor
Devemos registrar um aviso se os certificados SSL forem desativados ou substituídos, já que isso pode resultar em chaves roubadas? Ataque MITM e há algumas trocas usando dados de login como chaves (por exemplo, dx.exchange).
Deixe-me apenas adicionar:
aiohttp
( ccxt.async_support
) não descarta o aviso de certificado SSL.requests
( ccxt
) faz aviso de certificado SSL lance através urllib3
.@brandsimon , neste caso específico, o ataque MITM é feito deliberadamente pelo proprietário. Mas no geral sim, acho que seria ótimo ter um aviso para que a gente fique atento! )
@synchronizing thx pelas dicas!
Comentários muito úteis
https://travis-ci.org/ccxt/ccxt/builds