uibakery / axios-http2-adapter

HTTP/2 adapter for axios
https://github.com/uibakery/axios-http2-adapter
MIT License
39 stars 2 forks source link

`http2.Agent(opts)`, `opts` prop not respected #7

Closed skilbjo closed 1 month ago

skilbjo commented 9 months ago

hi, when i pass in properties to http2.Agent per the README, i can confirm that these properties are not respected

as you can see, i try to force TLSv1.2; but the connection is over TLSv1.3 and the ciphers are not respected - any idea why ?

the website https://check.ja3.zone/ is v helpful for seeing the connection details

here is a POC

script.mjs

import https from 'node:https';
import tls from 'node:tls';
import axios from 'axios';
import { createHTTP2Adapter } from 'axios-http2-adapter';
import http2 from 'http2-wrapper';

const defaultCiphers = tls.DEFAULT_CIPHERS.split(':');
const shuffledCiphers = [
  defaultCiphers[0],
  defaultCiphers[2],
  defaultCiphers[1],
  ...defaultCiphers.slice(3, 5),
].join(':');

const opts = {
  ciphers: shuffledCiphers,
  honorCipherOrder: true,
  maxVersion: 'TLSv1.2',
  minVersion: 'TLSv1.2',
};

export const userAgent = {
  'User-Agent':
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/113.0',
};

export const defaultHeaders = {
  ...userAgent,
  Accept: '*/*',
  'Accept-Encoding': 'identity',
  'Accept-Language': 'en-GB,en;q=0.9',
};

// eslint-disable-next-line @typescript-eslint/no-floating-promises
(async () => {
  try {
    console.log({ opts });

    const response = await axios.request({
      adapter: createHTTP2Adapter({
        agent: new http2.Agent(opts),
        force: true, // Force HTTP/2 without ALPN check - adapter will not check whether the endpoint supports http2 before the request
      }),
      headers: {
        ...defaultHeaders,
      },
      // httpsAgent: new https.Agent(opts),
      method: 'GET',
      url: 'https://check.ja3.zone/',
    });

    console.log({
      headers: response.headers,
      response: response.data,
    });
  } catch (error) {
    console.error(error);
  }
})();

output

{
  opts: {
    ciphers: 'TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256',
    honorCipherOrder: true,
    maxVersion: 'TLSv1.2',
    minVersion: 'TLSv1.2'
  }
}
{
  headers: Object [AxiosHeaders] {
    ':status: 200\ncontent-length: 1888\ncontent-type: application/json\naccess-control-allow-origin: *': undefined
  },
  response: {
    hash: '1a28e69016765d92e3b381168d68922c',
    fingerprint: '771,4866-4867-4865-49199-49195-49200-49196-158-49191-103-49192-107-163-159-52393-52392-52394-49327-49325-49315-49311-49245-49249-49239-49235-162-49326-49324-49314-49310-49244-49248-49238-49234-49188-106-49187-64-49162-49172-57-56-49161-49171-51-50-157-49313-49309-49233-156-49312-49308-49232-61-60-53-47-255,0-11-10-35-16-22-23-13-43-45-51,29-23-30-25-24-256-257-258-259-260,0-1-2',
    ciphers: 'TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_GCM_SHA256,ECDHE-RSA-AES128-GCM-SHA256,ECDHE-ECDSA-AES128-GCM-SHA256,ECDHE-RSA-AES256-GCM-SHA384,ECDHE-ECDSA-AES256-GCM-SHA384,DHE-RSA-AES128-GCM-SHA256,ECDHE-RSA-AES128-SHA256,DHE-RSA-AES128-SHA256,ECDHE-RSA-AES256-SHA384,DHE-RSA-AES256-SHA256,DHE-DSS-AES256-GCM-SHA384,DHE-RSA-AES256-GCM-SHA384,ECDHE-ECDSA-CHACHA20-POLY1305,ECDHE-RSA-CHACHA20-POLY1305,DHE-RSA-CHACHA20-POLY1305,ECDHE-ECDSA-AES256-CCM8,ECDHE-ECDSA-AES256-CCM,DHE-RSA-AES256-CCM8,DHE-RSA-AES256-CCM,ECDHE-ECDSA-ARIA256-GCM-SHA384,ECDHE-ARIA256-GCM-SHA384,DHE-DSS-ARIA256-GCM-SHA384,DHE-RSA-ARIA256-GCM-SHA384,DHE-DSS-AES128-GCM-SHA256,ECDHE-ECDSA-AES128-CCM8,ECDHE-ECDSA-AES128-CCM,DHE-RSA-AES128-CCM8,DHE-RSA-AES128-CCM,ECDHE-ECDSA-ARIA128-GCM-SHA256,ECDHE-ARIA128-GCM-SHA256,DHE-DSS-ARIA128-GCM-SHA256,DHE-RSA-ARIA128-GCM-SHA256,ECDHE-ECDSA-AES256-SHA384,DHE-DSS-AES256-SHA256,ECDHE-ECDSA-AES128-SHA256,DHE-DSS-AES128-SHA256,ECDHE-ECDSA-AES256-SHA,ECDHE-RSA-AES256-SHA,DHE-RSA-AES256-SHA,DHE-DSS-AES256-SHA,ECDHE-ECDSA-AES128-SHA,ECDHE-RSA-AES128-SHA,DHE-RSA-AES128-SHA,DHE-DSS-AES128-SHA,AES256-GCM-SHA384,AES256-CCM8,AES256-CCM,ARIA256-GCM-SHA384,AES128-GCM-SHA256,AES128-CCM8,AES128-CCM,ARIA128-GCM-SHA256,AES256-SHA256,AES128-SHA256,AES256-SHA,AES128-SHA,TLS_EMPTY_RENEGOTIATION_INFO_SCSV',
    curves: '001D:0017:001E:0019:0018:0100:0101:0102:0103:0104',
    protocol: 'TLSv1.3',
    user_agent: 'axios/1.6.7'
  }
}

if you comment the adapter above, and uncomment the httpsAgent above, you get the desired output (but connection was made over HTTP/1

      // adapter: createHTTP2Adapter({
        // agent: new http2.Agent(opts),
        // force: true, // Force HTTP/2 without ALPN check - adapter will not check whether the endpoint supports http2 before the request
      // }),
      httpsAgent: new https.Agent(opts),
=>

{
  headers: Object [AxiosHeaders] {
    'content-length': '381',
    'content-type': 'application/json',
    'access-control-allow-origin': '*',
    connection: 'close'
  },
  response: {
    hash: '9743f7cbdeb0092a2e166eebb1d57aec',
    fingerprint: '771,49199-49195-255,0-11-10-35-22-23-13,29-23-30-25-24,0-1-2',
    ciphers: 'ECDHE-RSA-AES128-GCM-SHA256,ECDHE-ECDSA-AES128-GCM-SHA256,TLS_EMPTY_RENEGOTIATION_INFO_SCSV',
    curves: '001D:0017:001E:0019:0018',
    protocol: 'TLSv1.2',
    user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/113.0'
  }
}
Tibing commented 1 month ago

Hi! Thanks for reporting this issue. Unfortunately, I don't have the capacity to fix it at the moment, but pull requests are welcome if you or anyone else has the time to work on it. I appreciate the help!