java - send https request to server ip address throws SSLHandshakeException - java

I need to send post request to server ip through HTTPS protocol. Here is my code:
HttpClient httpClient = HttpClients.createDefault();
String address = "https://100.100.100.100:90"; //just an example
HttpPost httpPost = new HttpPost(address);
httpPost.addHeader("charset", "UTF-8");
//set post data(not important here)
...
HttpResponse response = httpClient.execute(httpPost);
the last line throws this exception:
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
What's the problem and how can I solve this?
EDIT:
I don't know DNS name, so I need to use ip instead. I sent ajax request to that ip in browser, browser sends request, but requests stay in waiting mode. My Http Client is a simple java desktop application.

Probably the server you're trying to connect to doesn't accept requests using IP address.
In HTTP, this happens if the server is used for multiple domains / websites - it needs to know which one to give you and it does so based on the Host header. So if you want to connect by IP your client must be configured to send the correct Host (and must be able to do so).
Now in HTTPS protocol, on top of this the server also provides a server certificate during the handshake and this certificate is issued for a server hostname }likely a DNS name e.g. example.com) - again if you connect by IP and don't give your HTTP client any more info, the client cannot validate that the certifiate received from the server is issued for the correct hostname.

Related

Cannot make http GET request on localhost of the android device/emulator

I have made test application to investigate the issue related to http request. It is an android application where I'm making request to localhost:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://127.0.0.1")
.build();
try {
Response response = client.newCall(request).execute();
Log.v("krv", response.toString());
} catch (Exception e) {
Log.v("krv", e.toString());
}
As result on device emulator I have "java.net.ConnectException: Failed to connect to /127.0.0.1:80" exception. With any other request on an external resource(like google.com) all are Ok. Also I have installed IIS. Operating system is Windows 10.
P.S. Really what I need - to be able to make http request on stb device where http server is run(where I have the same problem). I guess both issues have similar reason. Could you give me any advice how to fix/debug my problem...
127.0.0.1 is the loopback address for localhost. But when you're inside an android OS, the localhost or 127.0.0.1 is android itself and that is not where your server is running.
If you want to connect to the host machine, you need to find out the IP address of your host machine (Windows 10) and use that IP address instead of 127.0.0.1.
See How to find your local IP address
However, If you want to refer to the computer which is running the Android emulator, use the IP address 10.0.2.2 instead.

How to get server IP address in custom HostnameVerifier

I am having a custom verify method implemented from HostnameVerifier.
#Override
public boolean verify(String hostname, SSLSession session) {
The hostname here gives me the value present in the URL to which the client connects to (either IP address or dns name) and the SSLSession gives me all peer values like peerCert (in my case server certs) and peerCertChain. It also has peerHost which is value from the URL.
I am trying to get the server IP address that my client connecting to. The servers (2 in number) are behind Load Balancer. So my client URL will always have the Load Balancer IP while invoking server.
hostname
peerHost=session.getPeerHost()
These both are giving me the value from URL (that is loadBalancer IP).
How to get the IP address of the server which is behind load balancer in my custom HostnameVerifier?
SSLSession has got server certificates.. how can I get server IP address?
Any suggestion/help on this much appreciated
It is impossible to get the IP address of the server behind a load balancer from the connection because the connection is to the load balancer and not to the server. The only way you could get to the servers address is if the load balancer would tell you its address.
Assuming that the load balancer is the endpoint of the TLS connection and can modify the HTTP traffic inside the TLS it would be possible to add a custom HTTP header in the response. But, this information would only be available after the TLS handshake is done, i.e. not yet in the HostnameVerifier because this is called during the TLS handshake.
If the load balancer is not the endpoint of the TLS connection but just forwards the TCP connection unchanged to the server you still cannot get the IP address from the connection but you might distinguish the servers if they use different certificates. The content of the certificate should be accessible in HostnameVerifier.

Java HTTP Request on VPN only website

I am trying to build a website parser for one of our internal websites (accessible only from the company network - we get on the network through Cisco AnyConnect VPN).
I can access the site fine in any browser, but not using HTTP requests. Windows network and sharing center shows that I have two active networks:
The actual internet connection
The company network (without internet access).
Default HTTP client gets time out as I suppose it makes a request using the actual internet connection (and the website is not accessible to public), but using this code:
HttpParams params = httpClient.getParams();
params.setParameter(ConnRoutePNames.LOCAL_ADDRESS, InetAddress.getByName("10.x.x.x"));
I get the following error:
I/O exception caught when connectiong to /10.x.x.x -> {s} -> https://zzz.com:443: Network is unreachable: connect
Also, might be a stupid test but I have done a HTTP request to a "what is my ip" site and the IP is shown as my Wifi IP not the IP through VPN (which I get when I open browser and browse to a "what is my ip" website). Same thing (wrong IP) when I try this using a gui-less browser (Jaunt or HTMLUnit).
Please advise if any fixes for this.
ConnRoutePNames appears to be deprecated. See if the following works (I haven't tested):
HttpHost proxy = new HttpHost("10.x.x.x", 80);
HttpRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
CloseableHttpClient httpclient = HttpClients.custom()
.setRoutePlanner(routePlanner)
.build();

Moving from a web service from HTTP to HTTPS

I have a web service on one server and a Java client on another. Currently all calls are being made over HTTP but I would like the service to be more secure with HTTPS and basic authentication, I only want my client to be able to make calls. My web server receiving the requests is Apache httpd.
I've set up directives in the apache conf as follows:
<Location /mypath>
Order Deny,Allow
Deny from all
Allow from all
AuthType Basic
AuthName "My Web Service Login"
AuthBasicProvider file
AuthUserFile "/usr1/apache/passwd/passwords"
Require user myuser
</Location>
The passwords file has only one entry, for myuser
<IfModule ssl_module>
ServerName www.myserver.com
SSLEngine on
SSLCACertificateFile "/usr1/apache/conf/ssl/myCAList.pem"
SSLCertificateFile "/usr1/apache/conf/ssl/myserver.crt"
SSLCertificateKeyFile "/usr1/apache/conf/ssl/myserver.pem"
SSLVerifyClient require
</IfModule>
I think I have the server set up correctly (posted just in case). However, I can't test this for another hour when I can safely restart apache.
What I need help with is I'm unsure of how to configure the client. Here is a simple example call (using httpclient 4.5.1) :
HttpClient client = HttpClient.createDefault();
HttpGet httpGet = new HttpGet(URI);
HttpResponse httpRes = client.execute(httpGet);
I know I need to specify https instead of http on the URI, but how do I
1) Send the username and password for the basic authentication
2) Make sure my client server trusts the certificate of the web service server
3) What certificates and such that I need on the client server for the SSL connection
Thank you!

RestTemplate: login by certificate

I am writing a java rest-client to fetch data from the web App. I am trying to use client authentication(login using client certificate) mechanism using spring's RestTemplate to get authenticated on server.
Here are the steps that I did.
Server side:
Configure the web server to allow certificate based login. Set "clientAuth"= "want" in server.xml
Create a clients x509 certificate and add it into servers truststore.
Client Side
Initialize RestTemplate with clients trustStore and keyStore. For this I used org.apache.commons.httpclient.contrib.ssl.AuthSSLProtocolSocketFactory.
AuthSSLProtocolSocketFactory is initialized with client keystore in PKCS12 format, and client truststore (jks format).
Code looks like this:
CommonsClientHttpRequestFactory factory = (CommonsClientHttpRequestFactory) restTemplate.getRequestFactory();
HttpClient client = factory.getHttpClient();
client.getState().setAuthenticationPreemptive(false);
Protocol myHttps = new Protocol(HTTPS, secureProtocolSocketFactory, DEFAULT_HTTPS_PORT);
Protocol.registerProtocol(HTTPS, myHttps);
client.getHostConfiguration().setHost("localhost", DEFAULT_HTTPS_PORT, myHttps);
When I am making rest calls into server I am expecting the request to get authenticated by certificate. But I am getting http 403-forbidden error. It seems that restTemplate is trying to authenticate the request by basicCredentials, where my intent is to authenticate using certificate.
Following is the output logged by http client:
MultiThreadedHttpConnectionManager:390 - HttpConnectionManager.getConnection: config = HostConfiguration[host=https://<server-ip>], timeout = 0
MultiThreadedHttpConnectionManager$ConnectionPool:739 - Allocating new connection, hostConfig=HostConfiguration[host=<server-ip>]
HttpMethodDirector:160 - Preemptively sending default basic credentials
HttpMethodDirector:277 - Authenticating with BASIC <any realm>#<server-ip>:443
HttpMethodParams:355 - Credential charset not configured, using HTTP element charset
HttpConnection:691 - Open connection to 10.112.253.152:443
HttpMethodBase:1235 - Adding Host request header
RestTemplate:559 - GET request for "https://<server-ip>:443/url/" resulted in 403 (Forbidden)
Is there anything else that needs to be configured on RestTemplate to get authenticated using client certificate?

Categories

Resources