Kerberos auth with java times out on external network - java

I followed this article to create a java program for testing kerberos authentication: https://docs.oracle.com/javase/jndi/tutorial/ldap/security/gssapi.html
The only thing I changed were the configuration files.
The program works fine when I point the DNS settings of my windows client to my internal windows DNS/Kerb server but it times out when I use a separate public DNS server, even though:
1. My internal server has ports tcp/udp 88 open
2. My external server has the SRV records needed (_kerberos._tcp and _kerberos._udp on port 88)
3. I'm able to achieve kerberos authentication, with and without a user certificate, using my iPad which is not using my windows server's DNS
Both the iPad and my other clients are using the same network (my home wifi) and I've also tried by sharing out the data connection from my cell phone.
Given #3 above and the fact that the java program works from a client that uses my internal DNS, I'm a bit baffled as to why my java program wouldn't work in both scenarios (i.e. using the internal or external DNS server).
Do you have any suggestions?

From GitBook Hadoop and Kerberos: The Madness Beyond the Gate section Error Messages to Fear
Switching Kerberos to use TCP rather than UDP makes [some bizarre
issues] go away ... Note also UDP is a lot slower to time out ...
Kerberos waits ~90 seconds before timing out, which is a long time to
notice there's a problem ...
In /etc/krb5.conf
[libdefaults]
udp_preference_limit = 1
PS: the "~90 seconds before timing out" may refer specifically to the Java-specific defaults i.e.
kdc_timeout = 30000
max_retries = 3
Generally speaking, UDP seems to be a root cause for many weird Kerberos issues, cf. How to save Kerberos Service Ticket using a Windows Java client? for instance.
Disabling it systematically might be a "good practise".

Related

Multiple spring boot instances on different ports - login/logout problem

I'm setting up a new dev environment on a windows 10 pro installation. Therefore i am exporting my spring-boot applications as .jar file and start it as windows service on different ports.
Spring boot app 1 on port 10001
Spring boot app 2 on port 10002
and so on
I already unlocked those ports in my firewall and everything seems working perfectly fine.
When I log into the application with port 10001, everything seems fine as well. However as soon as i log into another application (10002) i get automatically logged off on the 10001 application.
To sum it up, I am only able to be logged into one application at a time.
I am using a MySql8 Server installation. All applications have their own databaseschema. Additionally i am using spring security for authentication.
Because all those applications are running perfectly fine on our productive server (jelastic web hosting) it should have something to do with my dev environment instead of a code issue.
I'm happy you solved your problem. I don't think that using SSL and subdomains is the most simplistic solution to your problem though, especially if you are running automated tests in that environment, ssl might slow you down a bit.
There is a well known address you can bind your application to: 127.0.0.1. However, most people don't know, that your loop back device is actually listening to 127.0.0.1/8 in other numbers 127.0.0.1 with a netmask of 255.0.0.0 which means you can bind your services to any address in a whole class a subnet.
TLDR: try binding your application 1 to 127.0.0.2 and application 2 to 127.0.0.3. That should help with the cookies and later on, if you add monitoring ports, will make your life of managing port numbers easier.
As already mentioned in my comment above, the problem is not related to any software bug, instead its just how http is defined:
"Cookies do not provide isolation by port. If a cookie is readable by a service running on one port, the cookie is also readable by a service running on another port of the same server."
Are HTTP cookies port specific?
I solved my issue by using SSL encryption and different subdomains.

How to create a public url for a Webapp

I have been given an assignment for User registration and login using Spring boot. Front end I have used thymeleaf.I have developed the application in my localhost.
Below are the deliverable
Deliverables
● Source code ---- Done with GitHub
● Public working url of the webapp --- How to do???
● Tests - unit and integration tests. you may also choose to use a ci ---- Done
I would like to know how to create a public working URL for a project developed on localhost.
This process is called deployment. You may use Heroku, just follow the instructions. At the end, you will get an URL like http://my-lovely-app.herokuapp.com/ which is public and working.
Just go to the command line and navigate to your program by typing “cd (the path to your web app)”. Then in the command line type “gcloud app deploy”. Then click on the link to your site.
to answer this question, one needs first to understand an overview of an http(s) request lifecycle:
user enters an URL in his browser: https://some.domain:8080/request/path?param1=value1&param2=value2
the browser splits the URL into protocol scheme ("https"), server DNS name ("some.domain"), port (8080), request path ("/request/path") and query-string ("param1=value1&param2=value2"). If a port is omitted, the default port for the given protocol is assumed (80 for HTTP, 443 for HTTPS, etc)
the browser performs a DNS lookup to translate server DNS name to an IP address.
the browser makes a TCP connection to server's IP address (in theory HTTP can also use UDP, but it is rarely used, so we will skip this case)
if HTTPS was used, the browser and the server perform TLS handshake during which, among others, they exchange and verify each other's SSL/TLS certificate chains (usually it's only server presenting its certs and the browser verifying them, but you can also install client certificate and a key in your browser)
the browser sends the HTTP request over TLS (in case of HTTPS) or over bare TCP (in case of HTTP) to the server.
the server running software appropriate to execute your app routes the request to it to obtain a response that it will send back to the browser.
Points 1, 2 and 6 do not require any setup from you side.
For point 3 to work, you need to have a proper DNS record on some public DNS server.
For point 4 to work, your server needs to have a public IP address assigned by an ISP.
For point 5 to work, your server needs to have installed a valid SSL/TLS certificate issued by some certificate authority (you can skip it if you need only HTTP)
For point 7 to work, your server needs to have appropriate software and your app installed similarly as your local dev machine.
There are a lot of services available that provide all 3 or some subset of them for you, some of them even for free up to some capacity.
Let's start with a server and an IP address:
the most hardcore and low-level approach is to buy a public IP from your ISP and host your app on your local machine. this is not recommended however because of availability issues: whenever there is any network or power outage or if you turn off your machine, your app will be down. other solutions provide much better level of service (they have redundant power sources, internet connections and staff making sure that everything works 24/7)
a bit higher level approach is to buy a virtual or dedicated server from some hosting company (search the web for "VPS", "dedicates server" or "VM hosting" to find one in your area. Well know global ones are for example Google Cloud Compute Engine, AWS EC2, M$ Azure, OVH). These companies will provide for you a server with a public IP, full administrative access (via SSH usually) and some guarantees on it's availability (usually ranging from 99% to 99.99% -> the more 9s the more expensive it is). After that you will need to install and configure all necessary software to run your app on such server. These companies often offer DNS entry in their subdomain and an HTTPS ceritficate in a package for a small to even zero fee. Many of them also offer packages containing a separate domain of your choice and sometimes a certificate.
the most high level solution is a cloud app service (like mentioned in the other answer Heroku, AWS Beanstalk, Google App Engine, kubernetes cluster etc). These services will provide a configurable size pool of instances hosting your app with some load balancing in front of them. This will make your app easy to scale and have a very high availability rate. This is the best solution in most cases: just make sure that the given service provider supports technology stack required by your app. Again, companies providing such services often have packages with DNS entries and HTTPS certificates.
If you need to buy a DNS domain separately (you didn't like any of the packages offered by the server provider) just search for "DNS names" or "domain names" and you will find a lot of resellers. These resellers will provide you a console where you can bind IP address of your server to the DNS name.
Finally if you need to obtain SSL/TLS certificate, you can also search for providers on the web or you can use free automatic certs from https://letsencrypt.org/
That's pretty much it.

JDBC Remote MySQL Connectivity

I'm developing a Java Swing based app which uses JDBC to connect to a MySQL database. As such, the software directly remotely access the database from whichever computer it happens to be running on. Additionally, the app uses prepared statements to query the database and the database is hosted on a shared CPanel hosting account (if that matters).
The snippet of code I use to connect to the database is as follows (fairly standard connect code I think and all strings in all caps contain the correct contents):
String url = "jdbc:mysql://URL:PORT/DB_NAME?connectTimeout=3000";
Connection conn = DriverManager.getConnection(url, USERNAME, PASSWORD);
I have only ever successfully used the app from one IP. Before I use the app from an IP, I have to manually whitelist the IP by adding it as an allowed remote MySQL access host. If I don't add the IP as an allowed access host, the server refuses my connection and I get the resultant error:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
Then if I whitelist an IP and try to connect from it, I don't get that error and the app connects to the database properly.
This system would be okay if the app were only going to be used from one IP, but it needs to work from any IP since I cannot predict who will download and use it. The only solution I see would be to do a global whitelist of all IPs in the allowed MySQL access hosts area. However, that seems like it has many drawbacks, such as being insecure as anyone who has the correct password could log in (and would thus be susceptible to brute force attacks). This seems to corroborate the hypothesis that that method is insecure. Thus, I would like to have a system of communicating between the app and database that is IP-independent (doesn't require whitelisting all the IPs).
Additionally (I don't know if this makes sense or matters), but I believe some of the areas I expect the app to be used in block certain protocols. Thus, (I think) I would like it if the selected method of communication only used HTTP or some other widely-used protocol.
I did some research into this problem and my efforts led me to 2-tier and n-tier models of database communication. Perhaps I could do something like make a PHP page which accepts a statement and a series of parameters (plus a password to gain entry), executes the statement, and then returns the result back as JSON. However, this seems like another less-than-ideal method as it seems like it would also have security problems.
I'm sure someone more experienced and knowledgeable than I has already come across this problem and developed a solution.
Therefore, my question: What is the preferred method of connecting to a MySQL database from a Java app in an IP-independent way?
I greatly appreciate and thank you for your time.
You're on the right track:
1) If you want any arbitrary client to connect directly to your database, and the clients can have any arbitrary IP address ... then you're probably going to have to effectly disable IP security be whitelisting all possible client IP addresses.
2) On the other hand, if you only allow local access to mySql (by far the most common scenario), then you can create a web app to interface between your clients and mySql.
SUGGESTION:
Consider creating a "REST" web service that your clients can talk to.
Here's a good tutorial that might help you get started:
REST with Java (JAX-RS) using Jersey - Tutorial
Q: Does your Swing app really need to emit "raw SQL"? Or can it make "high level" queries? REST is ideally suited for the latter.
PS:
Here's another, short example that might help suggest some design alternatives with REST, mySQL and Java for you:
http://www.9lessons.info/2012/09/restful-web-services-api-using-java-and.html
You are up against the policies -- primarily the security policies -- of your hosting provider. It's generally considered insecure to allow port 3306 (MySQL) connections from the whole internet. It certainly lays your MySQL server open to trivial denial-of-service attacks. (It just takes some knucklehead controlling a botnet to send in lots of port 3306 connection attempts. They don't even have to be successful connection attempts.) If you're sharing your MySQL server with other customers of your hosting provider, they have every incentive to restrict your remote access to their server.
Most folks who build database applications for deployment on the public internet do it by providing web services to hit the database with the specific operations required by the application. The application deployed at the end-user's machine then uses HTTP (or HTTPS for security) to access those web services. In turn the web services access the database. That's what multitier operations do. You're right that there are security problems, but you can mitigate them with careful development of your web service code.
You could use SSH tunneling to handle your database access. The SSH suite of remote-access applications allows port forwarding. To use this, you would establish (authenticated and encrypted) ssh connections between your end-users' machines and your database machine, that forward port 3306. Then your users could connect to localhost:3306, and that net traffic would be forwarded to your database server. It's pretty flexible and quite secure, if not completely simple to configure.
You might also investigate using SQL Relay. It's generally used for connection pooling and management within a data center network, but it might work for this purpose.
Be careful opening up your MySQL server to the world! If you do that you may want to require the use of TLS encrypted conections.

Java router port setup programmatically

I'm wondering if there is a way to setup connection between a client and a server over the internet and have both of them programmatic setup all needed router/firewall configuration changes to open needed external ports to communicate.
Assuming both server and client have known ip addresses and a DNS is not needed in this example to find the IP addresses. How might one have a server that when started configures access past the firewall and tells the router how to route proper communication to the server. I would assume the client may not need anything like this as it should only need to know the external IP address and port number of the server. If i'm wrong about my assumption please let me know.
Example if I have two houses house (A) has a server and house (B) has a client and both sites know what the other house external IP address is and know what port they will be using how may a Java application do all the configuration or at least do as much as possible on say windows,mac,ubuntu. The idea is the user of the server and client should not have to do a bunch of firewall/router configurations to get the application running. It would also be nice if in the example it shows how to release the connections when the server is terminated. Example when the java server is turned off it should close up port settings on the firewall and router. security and clean house.
There is no easy way of doing that as it will depend on the OS and on the many possible firewall application running on the machine. Plus, if your app crash, you will never set back the original parameters, which can be problematic when talking about security. Instead of trying to set up custom configuration, you should try to use standard communication template/protocol like http. This will gives you a high probability of your app running without additional configuration almost anywhere (since there is almost no point of having an internet connection if you don't allow http port).

Can I be sure my Java web app running on localhost:8080 is invisible from my fellow Starbucks customers?

I'm developing a Spring application on my Windows 7 machine and running it on localhost:8080.
Is there any chance that if I do this in a public location like Starbucks that it is possible for my app to be visible to others?
(I'm using Windows Firewall and Microsoft Security Essentials)
Be sure that it is binding to localhost:8080 (i.e., 127.0.0.1), not all interfaces (which is probably the default). Server programs usually have an option to say which IP addresses to bind. For example, in Apache, you can provide an IP address to the Listen directive in addition to a port number. If you only bind to 127.0.0.1, the port will not be open for people scanning your external IP address.
Short answer: No.
Long answer: Someone might access your app like this:
If you visit a malicious website (if anyone at Starbucks is poisoning the DNS cache or spoofing DNS responses then you may visit a malicious website at www.google.com not knowing about it) then the attacker may send you to his domain with a DNS server (which may in fact be on his laptop) replying to the same query with very short TTL once with his IP, then with 127.0.0.1, then his IP again, etc. That way when you are sent to (http://www.example.com:8080) it is resolved as the attacker's IP and you get the website which starts an AJAX request to the same domain and the same port (so the same origin policy is satisfied in every browser) but thanks to the short TTL you don't have the domain entry in your cache any more, so you ask again and this time you get the answer 127.0.0.1 which incidentally is your own loopback interface which you assume to be invisible from the outside - and it is in fact invisible from the outside but perfectly visible from your browser. Your browser will happily connect to your app at 127.0.0.1:8080 and proxy the request to the attacker with another AJAX connection or any other side channel. Voilà, your app is now connected to the world!
Things like this happen in the wild so be careful. Sometimes people even access admin interfaces in routers behind NAT and firewalls that way. Quite frankly I'm pretty scared by all of the responses telling you that it is impossible to access anything running on localhost. Be careful what you do.
Is there any chance that if I do this in a public location like Starbucks that it is possible for my app to be visible to others?
Of course! People can look over your shoulder.
what Jeremiah said. use netstat -an to check what addresses it bound to.
and never trust Windows firewall, or any other software to which you don't have the source.
If the port is open it can be. If you program it to only accept connections from localhost while developing then even if they can see it, they wont be able to connect to it.

Categories

Resources