LyleMi / ja3proxy

Customizing TLS (JA3) Fingerprints through HTTP Proxy
MIT License
95 stars 27 forks source link

Chaining another proxy? #10

Open atyachin opened 9 months ago

atyachin commented 9 months ago

Would it be possible to add an option to chain a second proxy between the ja3proxy and the final destination?

So the request would look like: client --> ja3proxy --> other_proxy --> destination server (goal is the pass the modified ja3 signature via the second proxy to the server)

The 2nd proxy params can be passed as parameters to ja3proxy.

Thanks!

LyleMi commented 8 months ago

Sure! We've added the option to add a second proxy using the parameter -upstream , you can use it like ./ja3proxy -upstream 127.0.0.1:1080.

You can refer to commit be41733 for more information.

atyachin commented 8 months ago

Amazing! Few questions please:

  1. Does it support proxy authentication in the form of user:pass@proxy_address:port ?
  2. Can I set a different proxy per request (this is important since many proxy providers are accepting parameters via the proxy username string).
  3. Can I set different ja3 client per request ?

Thanks much!

rosahaj commented 8 months ago

I have tried using the new -upstream parameter, but the connection isn't being tunneled through the specified socks proxy. I believe the issue is that CustomDialer is initialized in the line below, but isn't being used anywhere afterwards: https://github.com/LyleMi/ja3proxy/blob/be41733b1c5029c19c90ba52e9eeb69b3f83be0f/main.go#L39

Steps to reproduce:

# docker-compose.yml
services:
  ja3proxy:
    image: ghcr.io/lylemi/ja3proxy:latest
    build: .
    entrypoint:
      [
        "/app/ja3proxy",
        "-cert",
        "/app/credentials/cert.pem",
        "-key",
        "/app/credentials/key.pem",
        "-client",
        "360Browser",
        "-version",
        "7.5",
        "-upstream",
        "tor-socks-proxy:9150"
      ]
    ports:
      - 8080:8080
    volumes:
      - ./credentials:/app/credentials
  tor-socks-proxy:
    image: peterdavehello/tor-socks-proxy:latest

Then run:

docker compose up -d --build
curl -k --proxy http://localhost:8080/ https://ifconfig.co/ip

IP is the same as when running curl https://ifconfig.co/ip without a proxy.

LyleMi commented 8 months ago

I have tried using the new -upstream parameter, but the connection isn't being tunneled through the specified socks proxy. I believe the issue is that CustomDialer is initialized in the line below, but isn't being used anywhere afterwards:

It appears that the bug was caused by an incorrect commit, and one file was not properly submitted. Fixed it with new commit now.

LyleMi commented 8 months ago

Amazing! Few questions please:

1. Does it support proxy authentication in the form of user:pass@proxy_address:port ?
2. Can I set a different proxy per request (this is important since many proxy providers are accepting parameters via the proxy username string).
3. Can I set different ja3 client per request ?

Thanks much!

Regarding your question:

  1. Support for proxy authentication in the form of user:pass@proxy_address:port will be available later this week.
  2. Would launching multiple instances be a possible solution to meet your requirement?
  3. We will consider implementing support for setting different ja3 clients per request in future updates.

Best Regards

rosahaj commented 8 months ago

Amazing! Few questions please:

1. Does it support proxy authentication in the form of user:pass@proxy_address:port ?

2. Can I set a different proxy per request (this is important since many proxy providers are accepting parameters via the proxy username string).

3. Can I set different ja3 client per request ?

Thanks much!

I would second the wish for per-request options, which could be set using custom headers:

x-ja3proxy-upstream: socks://upstream-proxy/
x-ja3proxy-client: Chrome
x-ja3proxy-version: 120

The headers could be stripped out before the request is forwarded to the client. This would be great for scraping with a large proxy pool while using programming languages which don't support ja3 customization.

I have written a proof-of-concept for this using goproxy and tls-client: https://github.com/rosahaj/tlsproxy

atyachin commented 8 months ago

Per #2 - multiple instances won't work easily since proxy username contains parameters such as session_id, which means that every request may have a different proxy user...

LyleMi commented 8 months ago

@atyachin support proxy auth now. For 2 and 3, is https://github.com/rosahaj/tlsproxy a suitable solution for you?

atyachin commented 8 months ago

@LyleMi I'm currently testing the tlsproxy project. I noticed that it is based on the https://github.com/bogdanfinn/tls-client project for customizing the ja3 fingerprints. Do you know how is that library different from the TLS handshake process that you do in this project?

rosahaj commented 8 months ago

@LyleMi I'm currently testing the tlsproxy project. I noticed that it is based on the https://github.com/bogdanfinn/tls-client project for customizing the ja3 fingerprints. Do you know how is that library different from the TLS handshake process that you do in this project?

I can comment on that. tls-client is using uTLS under the hood, so the TLS handshake process is the same. Unfortunately tls-client uses https://github.com/bogdanfinn/fhttp instead of net/http, which makes it difficult to integrate with goproxy. tlsproxy currently segfaults on some requests due to a faulty conversion of fhttp responses to http responses - it's really just a proof-of-concept.

A much better approach would be to modify goproxy to use uTLS directly, then leverage goproxy's hook-like functionality to implement per-request options for upstream proxy and TLS fingerprint. At first glance, https://github.com/saucesteals/utlsproxy provides a really good basis for implementing all of the desired features. A mixture between ja3proxy's CA generation process, tlsproxy's API and utlsproxy's custom goproxy implementation would likely produce the most versatile and customizable TLS fingerprint mimicry proxy.

rosahaj commented 8 months ago

@LyleMi I'm currently testing the tlsproxy project. I noticed that it is based on the https://github.com/bogdanfinn/tls-client project for customizing the ja3 fingerprints. Do you know how is that library different from the TLS handshake process that you do in this project?

Update: I spent some time improving tlsproxy. Instead of tls-client, uTLS is used directly via Snowflake. The current implementation looks pretty stable - I'm able to proxy all Firefox traffic through it and visit any website without issues. So it's usable, but I won't be able to guarantee continued maintenance.

PandaWorker commented 8 months ago

I want you to add support for specifying raw data ja3 in header per request and global config I know that utls supports generating hello client from raw ja3.

const headers = {
  'x-tlsproxy-upstream': 'socks5://localhost:1234',
  'x-tlsproxy-ja3':  '771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-17513,29-23-24,0'
}

What do you think about this?

May be and add return socket with upstream proxy onConnect so that you can write in one open connection with proxy and one tls session? Openning connection with upstream proxy per request may be time consuming. Therefore, I suggest opening a connection on onConnect using the tls configuration from headers onConnect

wiop93256 commented 2 months ago

(Windows CLI) `D:\Dev_Tools\ja3Proxy\ja3proxy-v0.2-windows-amd64>ja3proxy.exe -port 8080 -client Chrome -version 58 -upstream "127.0.0.1:8866" flag provided but not defined: -upstream Usage of ja3proxy.exe: -addr string proxy listen host -cert string proxy tls cert (default "cert.pem") -client string utls client (default "Golang") -debug enable debug -key string proxy tls key (default "key.pem") -port string proxy listen port (default "8080") -version string utls client version (default "0")

D:\Dev_Tools\ja3Proxy\ja3proxy-v0.2-windows-amd64>`

Does ja3proxy-v0.2-windows-amd64.zip on windows is no update? Why i cant use param of "upstream"?

LyleMi commented 2 months ago

(Windows CLI) `D:\Dev_Tools\ja3Proxy\ja3proxy-v0.2-windows-amd64>ja3proxy.exe -port 8080 -client Chrome -version 58 -upstream "127.0.0.1:8866" flag provided but not defined: -upstream Usage of ja3proxy.exe: -addr string proxy listen host -cert string proxy tls cert (default "cert.pem") -client string utls client (default "Golang") -debug enable debug -key string proxy tls key (default "key.pem") -port string proxy listen port (default "8080") -version string utls client version (default "0")

D:\Dev_Tools\ja3Proxy\ja3proxy-v0.2-windows-amd64>`

Does ja3proxy-v0.2-windows-amd64.zip on windows is no update? Why i cant use param of "upstream"?

This is because v0.2 does not include the latest commit, you can try the new release @wiop93256