Kerberos: accessing host by IP address - java

I know that Kerberos does not work with IP adresses, it relies on domain names and correct DNS entries only.
But I found that old versions of overthere library allows to use IP address with Kerberos authentication.
I extracted code from overthere and created small java project that demonstrates that https://github.com/igolikov/KerberosWithIP
It uses Apache HttpClient to send WSMan request to hyper-v host.
I also found that it works with httpclient 4.3.3 and it doesn't work with httpclient 4.4.1
How it is possible that it works with IP?
UPD1. I suppose that httpclient or something in sun.security may use revers DNS lookup. I tried to intercept traffic with Wireshark, and found 1 Revers DNS lookup (in-addr.arpa), but it responded with "No such host" because default DNS server cannot do revers DNS for this IP.
UPD2. Here is server configuration
There are SPNs for host name and for IP address
SPN( 1 ) = WSMAN/10.10.64.60 1+=1
SPN( 1 ) = HOST/somehost.corp.org.com 1+=1
SPN( 1 ) = HOST/somehost 1+=1

Kerberos can work without DNS just fine, the problem DNS solves is both sides of the connection agreeing on the same service principal to use. If I use the kerberos API to fix that principal to standard one, then as long as the server side has that prinicpal in it's keytab it will continue to work.
I.E. you have to know the kerberos principal that the service you are connecting to uses before you can connnect. Most service principals are of the form
service/dns.name.of.host
But the service principal can be anything as long as the client software knows what to use "somehow".

Related

ERR_CERT_AUTHORITY_INVALID when accessing same hostname with different port

We have a splunk instance which is exposed to internet via say https://splunk.mycompany.com
When we access the above URL browser says connection is secure meaning all certificates are ok.
Now splunk REST API service is running on port 8089. So to access splunk REST API we have to hit
https://splunk.mycompany.com:8089
Whenever we are hitting the above URL we are getting certificate issues and browser is saying "your connection is not private"
Error is: NET::ERR_CERT_AUTHORITY_INVALID
As I am still accessing the same hostname via https (and a new port) it should establish a secure connection. But why it's failing to validate certificate authority?
Edit: I have been told by the splunk team to take ther certificate of https://splunk.mycompany.com and install in the java keystore in the machine from where the REST API call is being made. They also told this is working for otheres. My question why it is even needed?
You should enable SSL on port 8089 via server.conf file.
Have a look at the Splunk Documentation here: https://docs.splunk.com/Documentation/Splunk/9.0.0/Security/ConfigTLSCertsS2S

Gerrit 2.15.12 - Kerberos + GSSAPI + Active Directory - possible bug in sending SPN

Running on RHEL 7.5 with Java 8. Kerberos 5 release 1.15.1.
We are seeing a strange behaviour with this set-up that has been seen in all versions since 2.11.10.
Note, I can't post direct logs or config as it my company blocks this.
Steps to reproduce
1) Configure gerrit to use kerberos
gerrit.config
[container]
javaHome = <path to JRE>
javaOptions = -Djava.security.auth.login.config=<path to jaas.conf>
[auth]
type = LDAP
[ldap]
authentication = GSSAPI
server = ldap://<AD Realm>
<.. other AD related stuff..>
jaas.conf
KerberosLogin {
com.sun.security.auth.module.Krb5LoginModule
required
useTicketCache=true
doNotPrompt=true
renewTGT=true;
};
which is direct from the documentation.
2) kinit the keytab to create a ticket in the cache.
3) Try to login. It fails with "Server not found in Kerberos database (7)".
It will also fail if you change the jaas.conf to try and use the keytab directly.
You can access LDAP directly using the username/password but due to Company restrictions we can't have an unencrypted password at rest on a device so this is not a viable long, term solution.
We have taken packet captures of the traffic to the AD Realm and we see the same behaviour whether we use the keytab or the cache.
1) For the kinit we see one request to AD with the SPN field set to the SPN from the keytab. This, of course, works fine.
2) For any request from Gerrit we see TWO requests to AD, the first has the correct SPN from the cache/keytab the second tries to send an SPN of "ldap/" no matter what value of SPN is set. This second request is what is causing the error as that SPN is not recognised b AD.. Note, we have tried keytabs with various SPN's (HTTP/device, host/device, HTTP/device# etc etc). The same thing happens every time.
This may well be something very simple is wrong in our config but we have been banging our heads on this for weeks now.
The second request most likely shows up because you specified an LDAP server ldap://<AD Realm> in Gerrit's configuration. HTTP GSSAPI authentication may very well have succeeded at this point, but now the application needs to authenticate itself against the LDAP server before it can retrieve information about the user. That happens independently from the HTTP authentication itself.
It's normal that the SPN is not recognized because Active Directory generally doesn't use <AD Realm> to pick a domain controller – instead the individual server names have to be specified, e.g. ldap://dc01.ad.example.com. (Real AD clients choose a server automatically via DNS SRV records, but plain LDAP clients often don't support that.)
Note also that a keytab is essentially an unencrypted password at rest.

AWS API Gateway custom domain hostname doesn't match certificate

I have an api gateway setup. It has a custom domain name setup on a regional endpoint and is using a certificate in ACM. I am able to make successful requests to the custom name from my local machine and even with curl from the remote machine I'm attempting to use. However, from the java application running on the remote machine I see this
! javax.net.ssl.SSLException: hostname in certificate didn't match: <my.custom.domain.name.com> != <*.execute-api.us-east-1.amazonaws.com> OR <*.execute-api.us-east-1.amazonaws.com>
I have a route53 alias record pointing to the target domain name of the custom domain name endpoint configuration.
Any idea how to resolve this without just removing host checking from the java application.

Getting null value for request.getHeader("X-FORWARDED-FOR") while retrieving client IP address in java?

I have deployed my web application on Tomcat 6.0 in machine having ip address 10.xx.xx.90. Then i am making a http request(from browser) to this app from m/c having ip address (10.xx.xx.56).
I am trying to get the IP address of client(10.xx.xx.56) in my app using the below code. But I am getting null value for request.getHeader("X-FORWARDED-FOR") where as request.getRemoteAddr() returns the ip address of the machine on which the application is deployed i.e 10.xx.xx.90.
But, if I make a http call to the application from standalone java program I am able to get the client m/c ip address. So, what is the correct way to get the client IP address. Do I need to configure something in my tomcat ??
String ipAddress = request.getHeader("X-FORWARDED-FOR");
if (ipAddress == null) {
ipAddress = request.getRemoteAddr();
}
If you are using a reverse proxy you should know it. However, the end-client could presumably be behind a regular web-proxy. Anyway, the load balancer or proxy would set "X-Forwarded-For". From the Wikipedia article,
The X-Forwarded-For (XFF) HTTP header field is a de facto standard for identifying the originating IP address of a client connecting to a web server through an HTTP proxy or load balancer.
Based on your comments and question there isn't a proxy or load balancer. For best practices I would recommend you check that header first. If it's null then use request.getRemoteAddr() (which you reported as working).

In Java, how can a website find my real IP address while I'm behind a proxy?

My program will use (http) proxy to send out http requests. And the proxy address is known to the program. But the program also want to get the current IP address while behind proxy. What is the best way to retrieve that?
The only way you could do that would to have your program explicitly send its IP address to the server encoded in the request URL, a custom request header, or in the request body.
If the proxy is under your control, you could configure it to add your client's IP address to the request. (It may already do this; e.g. "x-forwarded-for")
The other problem (in general) is that the IP address of your machine could well be a private IP address. It is not guaranteed that the IP will be addressable by the server. Or if the server is using it to identify the client, then there is no guarantee the IP will be unique ... or reliable; e.g. not spoofed in some way.
There is one alternative though. If you configure your server and client correctly, the server can rely on an SSL client certificate to establish the identity of the client. But this requires a few things:
The user's firewall must allow HTTPS connections.
The client application (or user's browser) must have a client certificate in its keystore.
The server must be able to trust the client certificate and know what identity it establishes (a person? a machine?)
The client application must know to send the certificate when establishing the HTTPS connection.
There are also security issues with sending SSL/TLS through a proxy. There is the potential for "man in the middle" attacks if the proxy can't be trusted.
All in all, this is a "difficult" approach.
You could query What is my ip address?, or any of the other websites that can tell you (e.g. google what is my ip address).
do like this
String ipAddress = request.getHeader("X-FORWARDED-FOR");
if (ipAddress == null) {
ipAddress = request.getRemoteAddr();
}
System.out.println("ipAddress:" + ipAddress);

Categories