SSL handshake with Play having mismatch on hostnames - scala

We are using Play 2.5 + Scala and need to use SSL to connect to remote client using https.
The issue is the certificate that we got from client has CN something like api.*.*.*.net
but the actual URL we are trying to hit contains an IP Address :
https://123.234.34.56/service/resource/operation...
Since the common name in the certificate and the hostname(ipAddress) in the URL do not match , we are seeing the below error.
SSLHandshakeException: No subject alternative names present
So I tried to implement HostnameVerifier as shown below in Scala but this code is not being picked up by Play or Netty
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
{
public boolean verify(String hostname, SSLSession session)
{
// custom logic here to match hostname and IpAddress
return true;
}
});
I have no idea why Play/Netty is not picking it up during runtime, but we are hitting the remote client using Play WS :
import play.api.libs.ws.WS
WS.url(url).get()...
I am also thinking of trying the solution mentioned here :
Netty SSL hostname verification support
but not sure if I need to implement a ChannelFactory as per the above link as shown here http://netty.io/3.10/xref/org/jboss/netty/example/securechat/SecureChatClientPipelineFactory.html
Also I have seen somewhere else in SO posts that :
If the host name in the certificate doesn't resolve to the address, the server is mis-configured. Nevertheless, you should be able to alter your local DNS resolution to point that name to this IP address in your /etc/hosts file (if under Linux, or its Windows equivalent
I have no idea how to achieve this programatically in Java/Scala
Any help would be much appreciated !
Thanks
Suresh

The "hosts" fix looks like this:
Add a line like the following to your hosts file (instructions for Windows or Linux here)
123.234.34.56 api.a.b.c.net
Now connect to the server using the hostname "api.a.b.c.net", rather than its IP address
Because of the hosts override, your machine will not do a DNS lookup for this name, but will use that IP address. However, the SSL client will be satisfied that the hostname matches the cert and the error should go away.
For the HostnameVerifier fix, you need to follow the instructions in the answer you linked to. The Netty SSL client doesn't use the static global config that you are currently using.

Related

Grpc C++ DNS overrides

I am trying to connect a grpc-c++ client to a grpc-c++ server. I already have a grpc-java client connected with working TLS so the server should be functioning correctly.
However inside grpc-java there is a method when building a channel named 'overrideAuthority'. From the documentation the method
"Overrides the authority used with TLS and HTTP virtual hosting. It does not change what host is actually connected to. Is commonly in the form host:port."
I was attempting to find something similar for the c++ client. However, so far all I have found is a function named set_authority() on the grpc::ClientContext as well as two options used with grpc_channel_args which are GRPC_ARG_DEFAULT_AUTHORITY and GRPC_SSL_TARGET_NAME_OVERRIDE_ARG.
None of these seem to have any effect on the authority at all. The server will always reject the connection with the error
No match found for server name: 0.0.0.0.
P.S. I am aware that I can add it to the common name on the certificate (and I will if I need to). However, if possible I would like to follow the same pattern as the grpc-java client.
GRPC_SSL_TARGET_NAME_OVERRIDE_ARG is the right channel arg. Please take a look at some of the tests https://github.com/grpc/grpc/blob/470a3066c74abc7c2a0a2cab3b35000b27b51af1/test/core/end2end/fixtures/h2_ssl.cc#L133
https://github.com/grpc/grpc/blob/470a3066c74abc7c2a0a2cab3b35000b27b51af1/test/cpp/end2end/xds/xds_end2end_test.cc#L1348
Additionally, if I remember correctly, this log just serves as a warning and does not result in disconnections. Please collect some more verbose logs https://github.com/grpc/grpc/blob/master/TROUBLESHOOTING.md. That might give more hints as to what's going on here.

Is it possible to run an XMPP server without a domain name?

I need to run an XMPP server for IM with end-to-end encryption and voice calling. I'm trying to set up Prosody, but is it possible to run an XMPP server without a domain name? Without own DNS server and VPN network between clients?
Short Answer: Yes.
You can still configure a XMPP domain for your server. According to the standard, it doesn't has to be an DNS Name or IP address. Something like myserver is fine. Quoting RFC 7622 ยง 3.2:
The domainpart for every XMPP service MUST be a fully qualified domain
name (FQDN), an IPv4 address, an IPv6 address, or an unqualified
hostname (i.e., a text label that is resolvable on a local network).
But if you don't have a DNS name, then clients won't know automatically how to reach your server. Which means you have to configure the IP address and the port in every client.
You can use an IP address instead of a domain name, but if that address will be changing on a regular basis, you'll probably need modifications to standard XMPP servers and clients, as they'll not be expecting that.
I went through many Prosody tutorials and I think it is not possible to set up server based only on IP address and using SSL. I even have not found how to configure Prosody on local network with SSL and resolvable name like raspberry.local. My client always gave server not found, or incorrect communication.

Haxe: connecting to a remote host

I did the creating a client/server tutorial given here,
http://old.haxe.org/doc/neko/client_server,
but this example only really applies to the case of a local host which is of pretty limited utility. I was hoping that someone could explain how to extend this to the case of connecting to a remote host. Specifically, if someone knows how to modify this example such that I could run the server code from a laptop at home and have a friend (who knows my home ip) run the client.
Client code:
// file Client.hx
class Client {
static function main() {
var s = new sys.net.Socket();
s.connect(new sys.net.Host("localhost"),5000);
while( true ) {
var l = s.input.readLine();
trace(l);
if( l == "exit" ) {
s.close();
break;
}
}
}
}
Server code:
// file Server.hx
class Server {
static function main() {
var s = new sys.net.Socket();
s.bind(new sys.net.Host("localhost"),5000);
s.listen(1);
trace("Starting server...");
while( true ) {
var c : sys.net.Socket = s.accept();
trace("Client connected...");
c.write("hello\n");
c.write("your IP is "+c.peer().host.toString()+"\n");
c.write("exit");
c.close();
}
}
}
As a disclaimer, I know very little about communication protocols, so I apologize if the question is silly.
Edit:
If I replace "local host" with my local ip address "192.168.1.254" this still works, but if I replace "localhost" with my public ip address "206.XXX.XXX.XXX," the client does not connect (this was the first thing I tried).
I have disabled my firewall for both incoming and outgoing traffic on that port, but it doesn't seem to make a difference. Why is it that my client instance can only connect to the server instance locally? I would have though that changing the client code to use the public ip address of the computer route the request through the router.
Edit:
Turns out that it was actually working all along with the public ip address, but for whatever reason it could not connect to the router's public ip from within my local network (I still don't understand why this was a problem - maybe some weird router specific NAT problem). Using this utility:
http://www.yougetsignal.com/tools/open-ports/
I was able to verify that the relevant ports were open and connect to my server program.
In clients code in below string replace "localhost" with your IP-address:
s.connect(new sys.net.Host("localhost"),5000);
http://api.haxe.org/sys/net/Host.html
Creates a new Host : the name can be an IP in the form "127.0.0.1" or an host name such as "google.com", in which case the corresponding IP address is resolved using DNS. An exception occur if the host name could not be found.
This really depends on your home setup. Generally its a security risk to just open something on your home ip, so do this at your own risk.
Most likely you will have a dynamic ip address from your isp. This means that every time you connect to your isp your public ip may be different. Its common to use a third party service to get around this kind of thing. Many routers have a feature built in do to integrate with these providers but there are also native apps you can install. There are many services out there some free, some paid depending on what you want and who you trust eg http://www.noip.com/, http://dyn.com/dns/. These services will have getting started guides.
When its working you can change your client code from localhost to the public ip address and port you setup the dynamic dns service to expose.

getting SocketTimeoutException while using smack 4.1.2 in android to connect to my ejabberd server

I am trying to connect to ejabberd server using smack API 4.1.2 (no asmack) on android device. while running smackClient program , I am getting below error
java.net.SocketTimeOutException:Failed to connect to abc.example.com/182.*.*.* (on port 5222) after 30000ms,'abc.example.com:5222' failed because java.net.ConnectionException: Failed to connect to abc.example.com/182.*.*.* (on port 5222) after 30000ms
Connection to same ejabberd server using same android device is working fine using xmpp clients like xabber. so Issue is surely with client code I have written. Below is the snippet of my code
XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
.setUsernameAndPassword(userName, password)
.setServiceName("abc.example.com")
.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
.setSendPresence(true)
.build();
connection = new XMPPTCPConnection(config);
connection.connect();
connection.login(userName, password);
I am missing something in my client code that xabber is having so xabber connection is working from same device using same credential.
Please help
Hard to tell without real IP and names in your example. However, my best guess would be about how the address to your IP server is resolved.
There seems to be discrepancy in your example with server (example.com) and service name in your code (abc.example.com).
My guess it that your client is attempting to connect to another machine that the one the XMPP server is running on.
So, here are the things to check when you have issues with a server not replying:
Check how the address of the domain is resolved. You may need to specify another machine name that the domain. If this is a test domain, there is possibly not a DNS setup, so you may even need to specify server IP (while still configuring the client to use an XMPP domain, that's two different things).
In client, log the IP you are trying to connect to, to make sure this is the one where the server is running.
If server is not on the main domain server, you may even need to do DNS SRV record queries for XMPP C2S service.
For me , it took hours to find the solution.
I forget to turnoff the VPN application(Express VPN) .Network tunneling was the root cause .
And change the Network protocol version properties as below ,
Choose the 1st option (Obtain DNS server address automatically).
My experience: I used following code
DomainBareJid xmppServiceDomain = JidCreate.domainBareFrom("desktop-urvfr83");
//DomainBareJid xmppServiceDomain = JidCreate.domainBareFrom("192.168.1.3");
InetAddress addr = InetAddress.getByName("192.168.1.3");
XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
.setUsernameAndPassword("alir", "111111")
.setHostAddress(addr)
.setResource("phonn")
.setXmppDomain(xmppServiceDomain)
.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
.setPort(5222)
.build();
but it could not connect and produced timeout connection exception. When I disabled windows firewall it worked correctly and connected.

Using any/fake domains with ejabberd

I've recently purchased a cloud server which has public IP and I am using it to host an xmpp server.
My first task was to ensure my users connected using my subdomain - as an example m.chat.com.
In my configuration I have the following:
%% Hostname
{hosts, ["m.chat.com"]}.
I then created an admin user with that domain.
In parrellel I have created the following DNS record with my host provider, hostgator for my subdomain m.chat.com
Name TTL Class Type Record
m.chat.com 14400 IN A [IP of the server]
One thing that puzzled me was my ability to access the ejabberd web admin console. This was achieved via: [IP of the server]:5280/admin however I could not access it via m.chat.com:5280/admin
That aside, inside the web console, under "Virtual Hosts" I could see the host "m.chat.com". I created a user "user#m.chat.com" and tried to connect via Adium.
Inside Adium, simply typing in user#m.chat.com with the password did not work. Instead I had to also specify the "Connect server" which in this case was the [IP of the server].
It has connected fine and I have registered other users to check everything is working and it is.
Then I thought I'd go back to the ejabberd configuration and start messing around. I changed the hostname to the following:
%% Hostname
{hosts, ["m.chat.com", "facebook.com"]}.
I registered a user with that domain and restarted ejabberd. Upon checking the web console, to my surprise, I could see the Virtual host "facebook.com". I tested this user in Adium with the [IP of the server] defined in the "Connect server" section and it connected fine. I asked other people with their own internet connections to use this account on their PCs and they were able to connect too.
Story over - my question to everyone is how is this possible? Am I missing something? Is there no domain authentication. After searching online, it seems you can even use fake domains.
If I am to operate my own service in the future (iOS chat app) I do not want anyone using my domain names with their own public servers.
Can someone shine some light.
Thanks!
Edit: A second question - Preferably I do not want to have to define the "Connect Server" upon using a client. I would like the client to recognise the #m.chat.com domain and establish a connection to the Servers IP automatically. Have I configured my DNS record correctly? For anyone else using Hostgator, is there an additional task I must do?
Edit: I can now access the web console via m.chat.com:5280/admin and I no longer have to specify the Connect server when using a client. I didnt do anything, I think it was a case of Hostgater updating the DNS or something, they say it usually takes 4 hours. However I am still slightly puzzled as to why I can create accounts with the facebook.com domain. I understand that because I can not access the DNS admin for this domain I can not create any records but that does not prevent me from using the domain and just specifying a Connect server.
Your initial problems (unable to access the server by using m.chat.com) were almost certainly DNS issues, and it seems you have isolated that down to the time taken to update the record.
Your second question - about the fact that you can name virtual hosts without restriction, is simple but interesting. What makes you think there should be any kind of restriction? It would be like you dictating that I can't save "m.chat.com" in a file on my disk, or that I can't send "m.chat.com" in a message across the internet.
This is why DNS exists and is structured the way it is. Although I can tell my server that it hosts facebook.com, nobody will connect to it because the DNS record for facebook.com does not point at my server (users generally don't set the "connect host" manually). Which begs the question... why would I want to tell my server it hosts facebook.com, and if I did, why should Facebook care?
An additional, but relevant, identity layer on top of DNS are certificates - which clients should validate for the virtual host name in spite of any "connect host" set. Since it's not possible to have a certificate for facebook.com, clients should generally pop up warnings or fail to connect at all. If they don't, they're probably not validating the certificate correctly.