{"record":{"id":"d7b1250191e20b78","repo":"XX-net/XX-Net","slug":"sslwrapfail","errorCode":null,"errorMessage":"SslWrapFail","messagePattern":"SslWrapFail","errorType":"exception","errorClass":"SslWrapFail","httpStatus":null,"severity":"error","filePath":"code/default/smart_router/local/smart_route.py","lineNumber":315,"sourceCode":"\n\ndef do_gae(sock, host, port, client_address, left_buf=\"\"):\n    if not g.gae_proxy:\n        raise DontFakeCA()\n\n    sock.setblocking(1)\n    if left_buf:\n        schema = b\"http\"\n    else:\n        leadbyte = sock.recv(1, socket.MSG_PEEK)\n        if leadbyte in (b'\\x80', b'\\x16'):\n            if host != fake_host and not g.config.enable_fake_ca:\n                raise DontFakeCA()\n\n            try:\n                sock._sock = g.gae_proxy.proxy_handler.wrap_ssl(sock._sock, host, port, client_address)\n            except Exception as e:\n                raise SslWrapFail()\n\n            schema = b\"https\"\n        else:\n            schema = b\"http\"\n\n    sock.setblocking(1)\n    xlog.debug(\"host:%s:%d do gae\", host, port)\n    req = g.gae_proxy.proxy_handler.GAEProxyHandler(sock._sock, client_address, None, xlog)\n    req.parse_request()\n\n    if req.path[0] == b'/':\n        url = b'%s://%s%s' % (schema, req.headers[b'Host'], req.path)\n    else:\n        url = req.path\n\n    if url in [b\"http://www.twitter.com/xxnet\",\n                    b\"https://www.twitter.com/xxnet\",\n                    b\"http://www.deja.com/xxnet\",","sourceCodeStart":297,"sourceCodeEnd":333,"githubUrl":"https://github.com/XX-net/XX-Net/blob/cfa5bc17b67676e467f37ec50766127e0ab5f0aa/code/default/smart_router/local/smart_route.py#L297-L333","documentation":"do_gae calls g.gae_proxy.proxy_handler.wrap_ssl() to wrap the socket in the fake-CA TLS layer; if that raises any exception it is converted to SslWrapFail (the original exception is discarded). This means the local TLS handshake / certificate generation failed, e.g. missing or corrupted CA cert/key files or a handshake error with the client.","triggerScenarios":"TLS-routed GAE request where wrap_ssl throws — typical causes: CA cert/key files not generated yet, openssl errors generating per-host certificates, or client aborting the handshake.","commonSituations":"First run before the CA has been generated, deleted/corrupted certificate store, permission problems writing generated certs, client does not trust the CA and aborts.","solutions":["Check that the fake CA certificate and key exist and are readable; regenerate them if missing or corrupt","Ensure the process has write permission to the certificate generation directory","Install/trust the fake CA in the client OS/browser so handshakes complete","Log the original exception inside wrap_ssl call site to identify the root cause (current code swallows it)"],"exampleFix":"# before\ntry:\n    sock._sock = g.gae_proxy.proxy_handler.wrap_ssl(sock._sock, host, port, client_address)\nexcept Exception as e:\n    raise SslWrapFail()\n\n# after (preserve cause for debugging)\ntry:\n    sock._sock = g.gae_proxy.proxy_handler.wrap_ssl(sock._sock, host, port, client_address)\nexcept Exception as e:\n    xlog.warn('wrap_ssl %s fail:%r', host, e)\n    raise SslWrapFail()","handlingStrategy":"retry","validationCode":"import os\nca_ok = os.path.isfile(ca_cert_path) and os.path.isfile(ca_key_path)","typeGuard":null,"tryCatchPattern":"for attempt in range(2):\n    try:\n        do_gae(...); break\n    except SslWrapFail:\n        regenerate_ca() if attempt == 0 else try_next_strategy(sock, host, port)","preventionTips":["Generate and validate the fake CA before serving TLS traffic","Ensure write permissions for per-host cert generation","Keep the original wrap_ssl exception in logs for diagnosis"],"tags":["tls","ssl-handshake","fake-ca","gae-proxy"],"backgroundTag":"ssl-handshake-failure","analyzedSha":"cfa5bc17b67676e467f37ec50766127e0ab5f0aa","analyzedAt":"2026-08-27T19:28:28.225Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}