SSL handshake


(Roxtar) #1

Hello, I finally found my perfect notes taking app that meets all my requirements, I’m already using it on my private machine and it’s just amazing.

Thank you @craftzdog for this amazing app :grinning:

Bug report

I’m trying to make Inkdrop work on my corporate laptop, we’re behind I proxy, I already checked up with our system guys and they whitelisted *.inkdrop.app but I’m still unable to login :

Handshake failed

The SSL handshake could not be performed.

Host: api.inkdrop.app
Reason: Can’t initialize server context:handshakefailed:server state 1:state 9:Application response 500 handshakefailed

I tried the following snippet I found on this forum :

var request = require('request');
request('https://api.inkdrop.app/', function (error, response, body) {
  console.log('error:', error); // Print the error if one occurred
  console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
  console.log('body:', body); // Print the HTML for the Google homepage.
});

Which returns :

error: null
statusCode: 200
body: {“ok”:true}

So it should work, something strange is happening, do you have any idea about how to fix/avoid this issue ?

Thanks in advance for your help.

Info

  • Platform: (Windows)
  • Platform version: (Windows 1803)
  • App Version: (4.3.2)
  • Behind a corporate proxy but *.inkdrop.app has been whitelisted

Reproduce

  1. Start app
  2. Try to login
  3. ERROR

(Takuya Matsuyama) #2

Hi Roxtar,

Thank you for reporting it. Okay, let’s look into it.
That might be a library-dependent issue.
The app is currently using axios@0.19.0 for the api requests.
Can you please try this one?

const axios = require('axios')
axios.get('https://api.inkdrop.app/')
  .then(function (response) {
    console.log(response.data);
  })
  .catch(function (error) {
    console.log(error);
  })

(Roxtar) #3

Thanks @craftzdog for your quick transport :slight_smile:

{ 
    Error: Request failed with status code 500
        at createError (C:\ieu\ink\node_modules\axios\lib\core\createError.js:16:15)
        at settle (C:\ieu\ink\node_modules\axios\lib\core\settle.js:17:12)
        at IncomingMessage.handleStreamEnd (C:\ieu\ink\node_modules\axios\lib\adapters\http.js:237:11)
        at IncomingMessage.emit (events.js:203:15)
        at endReadableNT (_stream_readable.js:1145:12)
        at process._tickCallback (internal/process/next_tick.js:63:19)
    config:
    { url: 'https://api.inkdrop.app/',
        method: 'get',
        headers:
        { Accept: 'application/json, text/plain, */*',
            'User-Agent': 'axios/0.19.0',
            host: 'api.inkdrop.app' },
        transformRequest: [ [Function: transformRequest] ],
        transformResponse: [ [Function: transformResponse] ],
        timeout: 0,
        adapter: [Function: httpAdapter],
        xsrfCookieName: 'XSRF-TOKEN',
        xsrfHeaderName: 'X-XSRF-TOKEN',
        maxContentLength: -1,
        validateStatus: [Function: validateStatus],
        data: undefined },
    request:
    ClientRequest {
        _events:
        [Object: null prototype] {
            socket: [Function],
            abort: [Function],
            aborted: [Function],
            error: [Function],
            timeout: [Function],
            prefinish: [Function: requestOnPrefinish] },
        _eventsCount: 6,
        _maxListeners: undefined,
        output: [],
        outputEncodings: [],
        outputCallbacks: [],
        outputSize: 0,
        writable: true,
        _last: true,
        chunkedEncoding: false,
        shouldKeepAlive: false,
        useChunkedEncodingByDefault: false,
        sendDate: false,
        _removedConnection: false,
        _removedContLen: false,
        _removedTE: false,
        _contentLength: 0,
        _hasBody: true,
        _trailer: '',
        finished: true,
        _headerSent: true,
        socket:
        Socket {
            connecting: false,
            _hadError: false,
            _handle: [TCP],
            _parent: null,
            _host: '#PROXY#.#COMPANY#.ch',
            _readableState: [ReadableState],
            readable: true,
            _events: [Object],
            _eventsCount: 7,
            _maxListeners: undefined,
            _writableState: [WritableState],
            writable: false,
            allowHalfOpen: false,
            _sockname: null,
            _pendingData: null,
            _pendingEncoding: '',
            server: null,
            _server: null,
            parser: null,
            _httpMessage: [Circular],
            [Symbol(asyncId)]: 5,
            [Symbol(lastWriteQueueSize)]: 0,
            [Symbol(timeout)]: null,
            [Symbol(kBytesRead)]: 0,
            [Symbol(kBytesWritten)]: 0 },
        connection:
        Socket {
            connecting: false,
            _hadError: false,
            _handle: [TCP],
            _parent: null,
            _host: '#PROXY#.#COMPANY#.ch',
            _readableState: [ReadableState],
            readable: true,
            _events: [Object],
            _eventsCount: 7,
            _maxListeners: undefined,
            _writableState: [WritableState],
            writable: false,
            allowHalfOpen: false,
            _sockname: null,
            _pendingData: null,
            _pendingEncoding: '',
            server: null,
            _server: null,
            parser: null,
            _httpMessage: [Circular],
            [Symbol(asyncId)]: 5,
            [Symbol(lastWriteQueueSize)]: 0,
            [Symbol(timeout)]: null,
            [Symbol(kBytesRead)]: 0,
            [Symbol(kBytesWritten)]: 0 },
        _header:
        'GET https://api.inkdrop.app/ HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nUser-Agent: axios/0.19.0\r\nhost: api.inkdrop.app\r\nConnection: close\r\n\r\n',
        _onPendingData: [Function: noopPendingOutput],
        agent:
        Agent {
            _events: [Object],
            _eventsCount: 1,
            _maxListeners: undefined,
            defaultPort: 80,
            protocol: 'http:',
            options: [Object],
            requests: {},
            sockets: [Object],
            freeSockets: {},
            keepAliveMsecs: 1000,
            keepAlive: false,
            maxSockets: Infinity,
            maxFreeSockets: 256 },
        socketPath: undefined,
        timeout: undefined,
        method: 'GET',
        path: 'https://api.inkdrop.app/',
        _ended: true,
        res:
        IncomingMessage {
            _readableState: [ReadableState],
            readable: false,
            _events: [Object],
            _eventsCount: 3,
            _maxListeners: undefined,
            socket: [Socket],
            connection: [Socket],
            httpVersionMajor: 1,
            httpVersionMinor: 1,
            httpVersion: '1.1',
            complete: true,
            headers: [Object],
            rawHeaders: [Array],
            trailers: {},
            rawTrailers: [],
            aborted: false,
            upgrade: false,
            url: '',
            method: null,
            statusCode: 500,
            statusMessage: 'handshakefailed',
            client: [Socket],
            _consuming: true,
            _dumped: false,
            req: [Circular],
            responseUrl: 'http://#PROXY#.#COMPANY#.ch:80/https://api.inkdrop.app/',
            redirects: [] },
        aborted: undefined,
        timeoutCb: null,
        upgradeOrConnect: false,
        parser: null,
        maxHeadersCount: null,
        _redirectable:
        Writable {
            _writableState: [WritableState],
            writable: true,
            _events: [Object],
            _eventsCount: 2,
            _maxListeners: undefined,
            _options: [Object],
            _redirectCount: 0,
            _redirects: [],
            _requestBodyLength: 0,
            _requestBodyBuffers: [],
            _onNativeResponse: [Function],
            _currentRequest: [Circular],
            _currentUrl: 'http://#PROXY#.#COMPANY#.ch:80/https://api.inkdrop.app/' },
        [Symbol(isCorked)]: false,
        [Symbol(outHeadersKey)]:
        [Object: null prototype] { accept: [Array], 'user-agent': [Array], host: [Array] } },
    response:
    { status: 500,
        statusText: 'handshakefailed',
        headers:
        { 'content-type': 'text/html',
            'cache-control': 'no-cache',
            'content-length': '2956',
            'proxy-connection': 'Close' },
        config:
        { url: 'https://api.inkdrop.app/',
            method: 'get',
            headers: [Object],
            transformRequest: [Array],
            transformResponse: [Array],
            timeout: 0,
            adapter: [Function: httpAdapter],
            xsrfCookieName: 'XSRF-TOKEN',
            xsrfHeaderName: 'X-XSRF-TOKEN',
            maxContentLength: -1,
            validateStatus: [Function: validateStatus],
            data: undefined },
        request:
        ClientRequest {
            _events: [Object],
            _eventsCount: 6,
            _maxListeners: undefined,
            output: [],
            outputEncodings: [],
            outputCallbacks: [],
            outputSize: 0,
            writable: true,
            _last: true,
            chunkedEncoding: false,
            shouldKeepAlive: false,
            useChunkedEncodingByDefault: false,
            sendDate: false,
            _removedConnection: false,
            _removedContLen: false,
            _removedTE: false,
            _contentLength: 0,
            _hasBody: true,
            _trailer: '',
            finished: true,
            _headerSent: true,
            socket: [Socket],
            connection: [Socket],
            _header:
            'GET https://api.inkdrop.app/ HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nUser-Agent: axios/0.19.0\r\nhost: api.inkdrop.app\r\nConnection: close\r\n\r\n',
            _onPendingData: [Function: noopPendingOutput],
            agent: [Agent],
            socketPath: undefined,
            timeout: undefined,
            method: 'GET',
            path: 'https://api.inkdrop.app/',
            _ended: true,
            res: [IncomingMessage],
            aborted: undefined,
            timeoutCb: null,
            upgradeOrConnect: false,
            parser: null,
            maxHeadersCount: null,
            _redirectable: [Writable],
            [Symbol(isCorked)]: false,
            [Symbol(outHeadersKey)]: [Object] },
        data:
            '#REMOVED#'
    isAxiosError: true,
    toJSON: [Function] 
}

I voluntary removed some company’s informations (precise proxy URL and ‘data’ field which only contained our internal generated HTML error page (Handshake failed bla bla…)).

It looks like Axios doesn’t care about the strict_ssl: 0 config…


(Takuya Matsuyama) #4

Thanks for trying it out.
Well, I guess axios needs https-proxy-agent as httpsAgent like this:

const axios = require('axios')
const HttpsProxyAgent = require('https-proxy-agent')

axios.get('https://api.inkdrop.app/', {
    httpsAgent: new HttpsProxyAgent(YOUR_PROXY_HTTPS_URL)
  })
  .then(function (response) {
    console.log(response.data);
  })
  .catch(function (error) {
    console.log(error);
  })

Does it work?
Also please don’t forget to set NODE_TLS_REJECT_UNAUTHORIZED environment value to '0'.


(Roxtar) #5

Nope, unfortunately not… :sob:

{ 
    Error: write EPROTO 24160:error:1408F10B:SSL routines:ssl3_get_record:wrong version number:c:\ws\deps\openssl\openssl\ssl\record\ssl3_record.c:332:

    at WriteWrap.afterWrite [as oncomplete] (net.js:788:14)
    errno: 'EPROTO',
    code: 'EPROTO',
    syscall: 'write',
    config:
    { url: 'https://api.inkdrop.app/',
        method: 'get',
        headers:
        { Accept: 'application/json, text/plain, */*',
            'User-Agent': 'axios/0.19.0',
            host: 'api.inkdrop.app' },
        transformRequest: [ [Function: transformRequest] ],
        transformResponse: [ [Function: transformResponse] ],
        timeout: 0,
        adapter: [Function: httpAdapter],
        xsrfCookieName: 'XSRF-TOKEN',
        xsrfHeaderName: 'X-XSRF-TOKEN',
        maxContentLength: -1,
        validateStatus: [Function: validateStatus],
        httpsAgent:
        HttpsProxyAgent {
            _events: [Object: null prototype] {},
            _eventsCount: 0,
            _maxListeners: undefined,
            _promisifiedCallback: true,
            timeout: null,
            options: [Url],
            secureProxy: true,
            proxy: [Object],
            defaultPort: 443,
            callback: [Function] },
        data: undefined },
    request:
    Writable {
        _writableState:
        WritableState {
            objectMode: false,
            highWaterMark: 16384,
            finalCalled: false,
            needDrain: false,
            ending: false,
            ended: false,
            finished: false,
            destroyed: false,
            decodeStrings: true,
            defaultEncoding: 'utf8',
            length: 0,
            writing: false,
            corked: 0,
            sync: true,
            bufferProcessing: false,
            onwrite: [Function: bound onwrite],
            writecb: null,
            writelen: 0,
            bufferedRequest: null,
            lastBufferedRequest: null,
            pendingcb: 0,
            prefinished: false,
            errorEmitted: false,
            emitClose: true,
            autoDestroy: false,
            bufferedRequestCount: 0,
            corkedRequestsFree: [Object] },
        writable: true,
        _events:
        [Object: null prototype] {
            response: [Function: handleResponse],
            error: [Function: handleRequestError] },
        _eventsCount: 2,
        _maxListeners: undefined,
        _options:
        { protocol: 'http:',
            maxRedirects: 21,
            maxBodyLength: 10485760,
            path: 'https://api.inkdrop.app/',
            method: 'GET',
            headers: [Object],
            agent: [HttpsProxyAgent],
            auth: undefined,
            hostname: '#PROXY#.#COMPANY#.ch',
            port: '8443',
            nativeProtocols: [Object],
            pathname: 'https://api.inkdrop.app/' },
        _redirectCount: 0,
        _redirects: [],
        _requestBodyLength: 0,
        _requestBodyBuffers: [],
        _onNativeResponse: [Function],
        _currentRequest:
        ClientRequest {
            _events: [Object],
            _eventsCount: 6,
            _maxListeners: undefined,
            output: [Array],
            outputEncodings: [Array],
            outputCallbacks: [Array],
            outputSize: 152,
            writable: true,
            _last: true,
            chunkedEncoding: false,
            shouldKeepAlive: false,
            useChunkedEncodingByDefault: false,
            sendDate: false,
            _removedConnection: false,
            _removedContLen: false,
            _removedTE: false,
            _contentLength: 0,
            _hasBody: true,
            _trailer: '',
            finished: true,
            _headerSent: true,
            socket: null,
            connection: null,
            _header:
            'GET https://api.inkdrop.app/ HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nUser-Agent: axios/0.19.0\r\nhost: api.inkdrop.app\r\nConnection: close\r\n\r\n',
            _onPendingData: [Function: noopPendingOutput],
            agent: [HttpsProxyAgent],
            socketPath: undefined,
            timeout: undefined,
            method: 'GET',
            path: 'https://api.inkdrop.app/',
            _ended: false,
            res: null,
            aborted: undefined,
            timeoutCb: null,
            upgradeOrConnect: false,
            parser: null,
            maxHeadersCount: null,
            _redirectable: [Circular],
            _hadError: true,
            [Symbol(isCorked)]: false,
            [Symbol(outHeadersKey)]: [Object] },
        _currentUrl: 'http://#PROXY#.#COMPANY#.ch:8443/https://api.inkdrop.app/' },
    response: undefined,
    isAxiosError: true,
    toJSON: [Function] 
}

(Takuya Matsuyama) #6

Your proxy protocol seems to be ‘http’ and not ‘https’:

  • http://#PROXY#.#COMPANY#.ch:8443/

Can you please make sure if it should be https://#PROXY#.#COMPANY#.ch:8443/ since its port seems like https?


(Takuya Matsuyama) #7

Oh, I guess that YOUR_PROXY_HTTPS_URL can be http://#PROXY#.#COMPANY#.ch:80/.
I misunderstood about HttpsProxyAgent.
Could you try it again with your non-SSL proxy server?


(Roxtar) #8

The previous result posted is with the “non-SSL” proxy server.

Our proxy intercepts https traffic (https://www.zdnet.com/article/kazakhstan-government-is-now-intercepting-all-https-traffic/)[like in Kazakhstan] for “security reasons” :unamused:.

Normally this just works with other services, but I’ll ask them more details on how this is done.

In the meantime, is there anyway to skip login on app startup, I don’t need sync for now on my work machine so it would be ok for me, but I’m afraid that login on startup is the only way for you to check the subscription…


(Takuya Matsuyama) #9

Ah that’s too bad.
“wrong version number” means the proxy server speaks obsolete protocol that node.js no longer supports. Inkdrop’s node version is currently 10.2.0 which does not support protocols like TLSv1.0. (See the related issue)

I’m afraid that you can’t use Inkdrop without logging in.
I hope you will get it to work.