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.
Related
i am trying in every way to add the SNI to my client (jetty 11.0.9). The server requires me to send host_name, but there is no way with jetty. can anyone do it?
Jetty's HttpClient uses the Java SSLEngine to initiate TLS connections and will use SNI by default.
Just use one of the HttpClient.newRequest() methods to create a Request with either an absolute URI (that includes the authority, hostname, port) or the newRequest() methods that take a hostname / port pair.
Note that the Java SSLEngine will follow the TLS/SNI spec and will not send SNI if the destination host is localhost or an IP Address (you must use a hostname, always, with SNI)
I have successfully built a client and server (Jetty) over localhost. This means I launched the Jetty server (https://localhost:8444/ws) and ran the client locally on the same machine and the entire handshake process worked perfectly.
When the client and server run on different machines, the following error message is received:
Caused by: java.lang.RuntimeException : socket reset for TTL
at org.apache.cxf.transport.https.HttpsClient.DefaultHostnameVerifier.verify(DefaultHostnameVerifier.java:98)
at sun.net.www.protocol.https.HttpsClient.checkURLSpoofing(Https.Client.java:641)
at sun.net.www.protocol.https.HttpsClient.afterConnect(Https.Client.java:573)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
...
**Update: ** in response to Stefan D's question below: By separating both the client and server from each other, I mean to simply move the WAR file to another linux host with IP address XXX.YYY.ZZZ.abc and the client to a different linux host with IP address XXX.YYY.ZZZ.def.
TLS compares the hostname given in the URL for connection against the CN in the certificate. A mismatch leads to the error you struggeling on.
To satisfie this requirement, the parameter CN of the subject (owner) in the certificate must exactly match the DNS hostname whitch is configured to the IP address of your server.
I.e. if the machine with IP address XXX.YYY.ZZZ.abc has the DNS name flintstone than the CN (which is set during generation of CSR) must be set to flintstone. If the DNS name is located in a different zone than the FQDN must be used.
The subject (owner) CN of your certificate is root.localhost. I presume that this is not the DNS name of the machine. So as explained above the hostname verification fails.
If you create your own certificates than it is possible to use an IP address as CN but for certificates ordered by a trust center it's no more supported. Also you may face the fact that self signed certificates are refused. For this, a lot of tools (freeware/open source and commercial) can be found in the internet.
I have a raspberry running a mqtt broker and a java backend. I can't establish a connection from backend to broker since I've implemented ssl. I can connect the backend to the broker on raspberry from my IDE running on my MacBook like:
client = new MqttAsyncClient(
"ssl://my-domain.com:1883", "backend");
if the backend is on the raspberry I tried:
client = new MqttAsyncClient(
"ssl://localhost:1883", "backend");
client = new MqttAsyncClient(
"ssl://127.0.0.1:1883", "backend");
No success. I´ve never used a ssl connection in this context. did I oversee something?
Error:
Exception in thread "main" No connection to client (32104)
at org.eclipse.paho.client.mqttv3.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:31)
at org.eclipse.paho.client.mqttv3.internal.ClientComms.sendNoWait(ClientComms.java:143)
at org.eclipse.paho.client.mqttv3.MqttAsyncClient.subscribe(MqttAsyncClient.java:721)
at org.eclipse.paho.client.mqttv3.MqttAsyncClient.subscribe(MqttAsyncClient.java:681)
at com.cdh.Service.mqttManager.subscribe(mqttManager.java:243)
at com.cdh.main.main(main.java:14)
EDIT:
I changed the port to 8883. It works if I run the backend on an other device but not if the broker and the backend are on the raspberry. I also tried to use the domain name from my cert.
The hostname you use to connect needs to match the CN or SAN entries in the certificate presented by the broker or else it will fail validation.
Unless you included 127.0.0.1 or localhost in the certificate the the client will reject the connection because the certificate doesn't validate for that address.
p.s. you should probably use a different port for MQTT of TLS rather than 1883 as that is the standard port for MQTT without TLS.
I have two RMI java applications:
server
System.setProperty("java.rmi.server.hostname", "0.tcp.ngrok.io");
System.setProperty("java.security.policy", "security.policy");
if (System.getSecurityManager() == null) {
System.setSecurityManager(new SecurityManager());
}
Registry r = LocateRegistry.createRegistry(1099);
r.rebind("Calc", new CalculatorImpl());
client
System.setProperty("java.rmi.server.hostname", "0.tcp.ngrok.io");
System.setProperty("java.security.policy", "security.policy");
Calculator c = (Calculator) Naming.lookup("//0.tcp.ngrok.io:18872"+"/Calc");
int sum = c.add(1, 5);
Communication between the two is done with the help of Ngrok:
ngrok tcp 1099
result
Session Status online
Account nival (Plan: Free)
Version 2.2.8
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding tcp://0.tcp.ngrok.io:18872 -> localhost:1099
Connections ttl opn rt1 rt5 p50 p90
5 0 0.00 0.00 5.88 17.03
My problem is :
RemoteException
java.rmi.ConnectException: Connection refused to host: 0.tcp.ngrok.io; nested exception is:
java.net.ConnectException: Connection timed out: connect
I think the problem is at
System.setProperty("java.rmi.server.hostname","0.tcp.ngrok.io");
what should I put on the server and client at "java.rmi.server.hostname"?
(Sorry for my bad english)
In general it's only required on server side to show on what hostname exported stubs will be available to the world.
It is useful for example, when your server is in the intranet and listens on some interface lets say 192.168.2.1. NAT proxy can have ports forwarded to that host from internet. Normally RMI registry would report stubs being exported on address 192.168.2.1:someport. But obviously you cannot hit that address directly java.rmi.server.hostname comes in action. By setting that property, RMI registry will announce stubs being exported on given hostname insteed on actual intranet address, allowing clients to get to the stubs from outside world trough forwarded ports on NAT gateway.
So if your server is behind NAT, it should specify the domain that points to your NAT gateway from the Internet. If your server has external IP and its listening on that IP, then this property is not needed.
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.