Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTPS proxy support #8373

Open
itning opened this issue Apr 18, 2024 · 17 comments
Open

HTTPS proxy support #8373

itning opened this issue Apr 18, 2024 · 17 comments
Labels
enhancement Feature not a bug

Comments

@itning
Copy link

itning commented Apr 18, 2024

Currently, it is my understanding that okhttp supports two types of proxys: HTTP/SOCKS, which are the proxy types built into JDK, but the vast majority of the use cases involve HTTPS proxies; any plans to support them?

@itning itning added the enhancement Feature not a bug label Apr 18, 2024
@itning
Copy link
Author

itning commented Apr 18, 2024

Apache http client can support HTTPS proxy:

HttpHost proxy = new HttpHost("https","www.xxx.xxx",8888);
CloseableHttpClient client = HttpClients.custom()
                    .setProxy(proxy)
                    .build();

So can OKHTTP client support it also?

@yschimke
Copy link
Collaborator

I think we should support. I've set up tests to validate against other proxily servers but haven't been able to easily verify Https behaviour.

Do you have a public test server I can test against? That you know is working ?

@itning
Copy link
Author

itning commented Apr 18, 2024

I think we should support. I've set up tests to validate against other proxily servers but haven't been able to easily verify Https behaviour.

Do you have a public test server I can test against? That you know is working ?

Thanks so much for your reply. I don’t currently have a publicly available proxy for you to test; however this is the project we are working from to set up our proxy. I hope this is somewhat helpful.

@yschimke
Copy link
Collaborator

I confirmed with smokescreen that this clumsy workaround works

  val serverCert = """
      -----BEGIN CERTIFICATE-----
      MIIE+DCCAuCgAwIBAgIBBTANBgkqhkiG9w0BAQsFADBrMQswCQYDVQQGEwJVUzET
...
      B5Ird7f+U0bSPpszX4PMGbydhsuhnbqDamrT0Q==
      -----END CERTIFICATE-----
    """.trimIndent().decodeCertificatePem()
    
    val certs = HandshakeCertificates.Builder()
      .addPlatformTrustedCertificates()
      .addTrustedCertificate(serverCert)
      .build()

    val sslSocketFactory = certs.sslSocketFactory()

    val client = OkHttpClient.Builder()
      .proxy(Proxy(Proxy.Type.HTTP, InetSocketAddress("localhost", 4750)))
      .socketFactory(sslSocketFactory)
      .build()

@yschimke
Copy link
Collaborator

OK change in code is simple, except our dependence on java.net.Proxy is limiting.

@swankjesse would it make sense to have our own model for Proxy?

@yschimke
Copy link
Collaborator

yschimke commented Apr 20, 2024

A quick exploration, I'll revert some of this and see if it looks ok

#8377

@itning
Copy link
Author

itning commented Apr 24, 2024

Hi @yschimke @swankjesse, Do we have release date for this feature?

@yschimke
Copy link
Collaborator

I don't think clean support will make 5.0, as it would require a new Proxy domain model.

Instead I'm aiming to allow this workaround #8379

@itning
Copy link
Author

itning commented Apr 24, 2024

@yschimke Do you mean we can have a workaround method without changing the source code?

@yschimke
Copy link
Collaborator

@itning No, would require changing the client.

How are you configuring this proxy? Maybe I can see if there is a way to make that path work.

@yschimke
Copy link
Collaborator

We don't currently have a similar API to Apache

HttpHost proxy = new HttpHost("https","www.xxx.xxx",8888);

@itning
Copy link
Author

itning commented Apr 24, 2024

How are you configuring this proxy? Maybe I can see if there is a way to make that path work.

For now we use apache http client like this: #8373 (comment)

@yschimke
Copy link
Collaborator

yschimke commented Apr 24, 2024

This would require this clumsy workaround for OkHttp

#8373 (comment)

Or at minimum

   // create a ssl socket factory somehow
    val sslSocketFactory = OkHttpClient().sslSocketFactory

    val client = OkHttpClient.Builder()
      .proxy(Proxy(Proxy.Type.HTTP, InetSocketAddress("localhost", 4750)))
      .socketFactory(sslSocketFactory)
      .build()

@itning
Copy link
Author

itning commented Apr 24, 2024

// create a ssl socket factory somehow
val sslSocketFactory = OkHttpClient().sslSocketFactory

val client = OkHttpClient.Builder()
  .proxy(Proxy(Proxy.Type.HTTP, InetSocketAddress("localhost", 4750)))
  .socketFactory(sslSocketFactory)
  .build()

I use the code, but got error:

Exception in thread "main" java.lang.IllegalArgumentException: socketFactory instanceof SSLSocketFactory
	at okhttp3.OkHttpClient$Builder.socketFactory(OkHttpClient.kt:723)
	at xxx.main(xxx.java:178)

@yschimke
Copy link
Collaborator

Sorry, I should have been clearer.

It requires this PR, unless you wrap that socket factory again.

#8379

@itning
Copy link
Author

itning commented May 4, 2024

@yschimke I'm sorry to bother you again and request when I can use the solution you provided?

@yschimke
Copy link
Collaborator

yschimke commented May 5, 2024

For now, try something like this

      val client =
        OkHttpClient.Builder()
          .sslSocketFactory(socketFactory, trustManager)
          .proxy(Proxy(Proxy.Type.HTTP, it.remoteAddress()))
          .protocols(listOf(Protocol.HTTP_2, Protocol.HTTP_1_1))
          .socketFactory(socketFactory.asSocketFactory())
          .build()

  private fun SSLSocketFactory.asSocketFactory(): SocketFactory {
    return DelegatingSocketFactory(this)
  }

DelegatingSocketFactory would be something like

open class DelegatingSocketFactory(private val delegate: SocketFactory) : SocketFactory() {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Feature not a bug
Projects
None yet
Development

No branches or pull requests

2 participants