How can I configure HTTPClient to authenticate against a SOCKS proxy? - java

I need to set up proxy authentication against a SOCKS proxy.
I found out this post giving instructions that appear to work with common HTTP proxies.
httpclient.getHostConfiguration().setProxy("proxyserver.example.com", 8080);
HttpState state = new HttpState();
state.setProxyCredentials(new AuthScope("proxyserver.example.com", 8080),
new UsernamePasswordCredentials("username", "password"));
httpclient.setState(state);
Would that work with SOCKS proxies as well or do I have to do something different?

Java supports Socks proxy configuration via preferences:
socksProxyHost for the host name of the SOCKS proxy server
socksProxyPort for the port number, the default value being 1080
e.g.
java -DsocksProxyHost=socks.mydomain.com
(edit) For your example, if the socks proxy was configured in the way outlined before:
httpclient.getHostConfiguration().setProxy("proxyserver.example.com", 8080);
Credentials cred = new UsernamePasswordCredentials("username","password");
httpclient.getState().setProxyCredentials(AuthScope.ANY, cred);
You can also use this variant (without httpclient):
SocketAddress addr = new
InetSocketAddress("webcache.mydomain.com", 8080);
Proxy proxy = new Proxy(Proxy.Type.SOCKS, addr); // Type.HTTP for HTTP
So completing the previous example, we can now add:
URL url = new URL("http://java.sun.com/");
URConnection conn = url.openConnection(proxy);
HTH

The Features page of Apache HTTPClient says:
Transparent connections through SOCKS proxies (version 4 & 5) using native Java socket support.
With "transparent", I guess they mean that it works without you needing to do anything special. Do you have a SOCKS proxy available somewhere? Can't you just try it out to see if it works?

SOCKS is not supported by HttpClient 3 natively. You can try the SOCKS support in JDK as suggested by others. The side effect is that your whole JVM will go through the same SOCKS proxy.
Java 5 supports Username/Password authentication in SOCKS (type 2). All you have to do is to setup the authenticator like this,
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password.toCharArray());
}
});
Again, this may not work for you because it affects all authentication in your JVM (HTTP auth, Proxy Auth).

You can provide a custom socket factory which implements the SOCKS protocol, and register it as your default HTTP protocol handler. This solution has a limitation similar to tuergeist's answer above has - it applies globally, to any HTTP connection you'll establish through HttpClient.
If you find this a problem, take a look at this correspondence, where Oleg suggests using HttpClient 4.0, but also refers to a possible patch in HostConfiguration class for HttpClient 3.x.
Another possible solution, which is my personal favorite, is to write a wrapper HTTP proxy to the socks proxy.

I tried
System.setProperty("socksProxyHost", "socks.xyz.com");
System.setProperty("socksProxyPort", "1000");
and it's working fine.

Related

Configuring Jetty HTTP/2 Client to use my HostnameVerifier implementation

I am using Jetty HTTP2 Client 9.4.12 to support HTTP/2 server connection. It's working fine but on top of verifying the certificate, I also want to verify the Hostname using my javax.net.ssl.HostnameVerifier implementation. According to the doc https://www.eclipse.org/jetty/javadoc/9.4.12.v20180830/org/eclipse/jetty/util/ssl/SslContextFactory.html I can use setEndpointIdentificationAlgorithm("HTTPS") to enable hostname verification but how do I configure Jetty to use my implementation?
Thanks.
Jetty's HttpClient does not support javax.net.ssl.HostnameVerifier.
An enhancement request exists for this ...
https://github.com/eclipse/jetty.project/issues/3154
Feel free to comment on the open enhancement requesting it, and providing an example of how you would use it.
The support has been added in Jetty v9.4.15.v20190215.
final SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setHostnameVerifier((hostname, sslSession) -> {
// logic to verify hostname
return false;
});

Using Proxy server for Java application

So i have a java app that uses Google Analytics API to gather some info. I am putting this application to run in my oracle cloud managed server which has a firewall and blocks any web calls to work. So, they setup a proxy for me to use....I've never set up a proxy to work with a java application before, I've been reading at tutorials like this: http://docs.oracle.com/javase/1.5.0/docs/guide/net/proxies.html
And i have no idea how to set this up...anyone want to point me in the right direction?
You must tell your application that there's a proxy somewhere.
As the documentation says, you must set some properties in your virtual machine. You can do it programatically:
//Set the http proxy to webcache.mydomain.com:8080
System.setProperty("http.proxyHost", "webcache.mydomain.com");
System.setPropery("http.proxyPort", "8080");
// Next connection will be through proxy.
URL url = new URL("http://java.sun.com/");
InputStream in = url.openStream();
// Now, let's 'unset' the proxy.
System.clearProperty("http.proxyHost");
// From now on http connections will be done directly.
Or use https.proxy... if the connection is HTTPS.
Besides, if you have access to the application server start script, you could add those properties as VM properties with -Dhttp.proxyHost....
The solution in my case was to configure the JVM with a HTTPS proxy:
System.setProperty("https.proxyHost", "proxy");
System.setProperty("https.proxyPort", "3128");

Tomcat to talk to proxy server

I have an application deployed on tomcat in linux rhel 5 , now this application makes an external call to internet and my server is behind the proxy server , now how do I configure the tomcat server for it to understand the proxy.
Is there a configuration I can do to redirect all requests send by tomcat to external servers
Also to mention that I did make the entries into catalina.properties
http.proxyHost=
http.proxyPort=8080
Alternatively, configure them as VM parameters in catalina.bat.
-Dhttp.proxyHost=<> -DproxyPort=8080
Another approach would be to configure them at the application level. If you are using java's own api to invoke external url, the proxy could be set as follows. In case you are using another library like apache httpclient, it provides methods to configure the proxy.
SocketAddress proxyAddress = new InetSocketAddress(proxyHost, proxyPort);
Proxy proxy = new Proxy(Type.HTTP, proxyAddress);
URL url = new URL(externalURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);

Setting the virtual host port in Apache HttpClient

I use Apache Commons HttpClient 3.1 as a kind of reverse-proxy. This proxy server runs in a servlet container in port 8081, and proxies some of the requests to port 8080 on the same server. As the legacy server on port 8080 builds some absolute urls using the HTTP Host header, I want to explicitly set that header.
It is not possible to set the Host-header as you set other headers, as HttpClient automatically overrides the value you set. The only way I've found to change the Host-header is to set the virtual host:
HttpClient = ...
HttpMethod = ...
HostParams hostParams = new HostParams();
hostParams.setVirtualHost("localhost:8081");
hostConfiguration.setParams(hostParams);
hostConfiguration.setHost("localhost", 8080);
client.executeMethod(hostConfiguration, method);
But this doesn't work as it should because HttpClient seems to add the port it connects to, to the Host:
11:07:05.011 [qtp1813719644-21] DEBUG httpclient.wire.header - >> "Host: localhost:8081:8080[\r][\n]"
Is it any way I can fix this behaviour? If not, does Apache Httpclient 4.x behave differently?
As your problem is traversing a proxy (which in your case is a Servlet+HTTPClient), configure your client to use localhost:8080 as proxy and url as normal: http://localhost:8081/... :
hostConfiguration.setProxy("localhost", 8080);
hostConfiguration.setHost("localhost", 8081);

Java Proxy client class that supports authentication

I'm looking for a java socks Proxy client class that supports authetication, any suggestions? The java.net.Proxy does not support authentication.
Edit:
I can't seem to find a way that would attach authentication data to particular proxy host via socket. Authenticator.setDefault() allows only one set of credential.
Authenticator.setDefault(new Authenticator(){
protected PasswordAuthentication getPasswordAuthentication(){
PasswordAuthentication p=new PasswordAuthentication("xxx", "xxx".toCharArray());
return p;
}
});
Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("xxx.xx.xxx.xxx", xxx));
Socket sock = new Socket(proxy);
sock.connect(new InetSocketAddress(server,xx));
Java supports Socks proxy configuration via a registered java.net.Authenticator or via preferences as documented in the Networking Properties:
SOCKS protocol support settings
The SOCKS username and password are
acquired in the following way. First,
if the application has registered a
java.net.Authenticator default
instance, then this will be queried
with the protocol set to the string
"SOCKS5", and the prompt set to to the
string "SOCKS authentication". If the
authenticator does not return a
username/password or if no
authenticator is registered then the
system checks for the user preferences
"java.net.socks.username" and
"java.net.socks.password". If these
preferences do not exist, then the
system property "user.name" is checked
for a username. In this case, no
password is supplied.
socksProxyHost
socksProxyPort (default: 1080)
Indicates the name of the SOCKS proxy server and the port number that will be used by the SOCKS protocol layer. If socksProxyHost is specified then all TCP sockets will use the SOCKS proxy server to establish a connection or accept one. The SOCKS proxy server can either be a SOCKS v4 or v5 server and it has to allow for unauthenticated connections.
For client code examples, you can check this answer on Stack Overflow.
EDIT: Update of the answer as per comment
The side effect of the SOCKS support in JDK is that your whole JVM will go through the same SOCKS proxy. So this may not work for you.
The Authenticator affects all authentication in your JVM (HTTP auth, Proxy Auth). So again, this may not work for you.
In your case, a possible solution would be to use HttpClient from HttpComponents (the successor of the legacy Commons HTTP Client 3.x). Check out the samples and especially the Request via a proxy and Proxy authentication examples.
Use this HttpClient (Not Apache's),
http://www.innovation.ch/java/HTTPClient/
This is simply an URL handler so you can use the usual HTTPUrlConnection. It supports SOCKS and other proxy.

Categories

Resources