Detect proxy in Java/JSP - java

I'm working on project using Java, in which IP address will be identity of the client/user. So I'm facing one problem: where user can spoof their host identity, that can lead to false identity of the user. So, anyone know, how to detect whether the host is using proxy or not?
InetAddress thisIp = InetAddress.getLocalHost();
I'm using above code to detect the host IP address.

You cannot 100% reliably check this, but to cover the most proxies, you could check the presence of the X-Forwarded-For request header.
if (request.getHeader("X-Forwarded-For") != null) {
// Client is likely using a proxy.
}
There is no standard for this. Each proxy may have its own specific set of additional/custom headers. You could log the retrieved request headers and examine which headers are been set by certain proxies and then alter the code accordingly. Again, you cannot reliably check this. Some proxies may even have no additional headers at all. You'd need to maintain a list of IP addresses of "well known" proxies so that you can check getRemoteAddr() against it.
Unrelated to the concrete problem, as you tagged this with jsp, I would only add that writing Java code inside a JSP is a poor practice. You'd normally do this in a normal Java class like a servlet or a filter.

Related

java.security.cert.CertificateException: No subject alternative names matching IP address

I have different issues with this exception, Please try to understand.
I'm sending data from one application to another through web service call in Java.
whenever I called it will connect to some other application. in that
a situation I get the above exception, this problem occur only in
byte Grid server.
We solved above problem like this our admin removed security,
means we have https they removed s so we are working with
HTTP, but it's not good, I want to connect through web service call with security, can any one give me the best idea.Please see my sample code
byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8);
int postDataLength = postData.length;
String request = PropertyFactory.getProperty("someUrl");
url = new URL(request);
postConnection = (HttpURLConnection) url.openConnection();
can I handle through code?
If you are using Oracle JDK between 1.8.0_51 and 1.8.0_60, there was an issue when connecting via IP address instead of hostname. In the case of using the IP-address, this address also has to be mentioned in the Subject alternative names of the cert. According to Mulesoft Support a workaround would be to set the JVM argument "jdk.tls.trustNameService" to true - resulting in a reverse name lookup for the IP address.
Byte grid having internal firewall so its may be stop, Please contact with byte grid team.

Identifying a client behind router/firewall

In my web-app I need to register http clients accessing from a local network behind a router.
I started with remoteHost : remotePort combination, but soon enough it became clear, that the port numer gets regenereated upon each connection.
I need to be able to identify the clients on something similar to MAC address, some property that doesn't change. I wanted to use headers[ "X-Forwarded-For" ], but it's not present at all:
[Pragma=no-cache, Cache-Control=no-cache, Host=somhost.com:8822, Upgrade=websocket, Connection=Upgrade, Sec-WebSocket-Key=scnlM7hzjjy3cklJhJciA==, Sec-WebSocket-Extensions=x-webkit-deflate-frame,deflate-frame, Sec-WebSocket-Version=13]
What are the other options to identify clients?
You could use an API key, that is, a unique identifier that the clients send along with each request to identify themselves. Depending on the authentication method you are using, you could consider the standard HTTP Authorization header to send this value:
Authorization: API-Key <value goes here>
Or create a custom HTTP header for this purpose. But be careful with custom headers: proxies might strip them out.
One option is using cookies. As the client accesses the webapp for the first time we could set a cookie on the client side that has a very long expiry date.
During the subsequent user re-logins we can rely on this cookie as cookies get sent to the server.
You can try this bit of PHP to see what the server knows about an incoming http request:
$keys = array_keys($_SERVER);
echo "<table bgcolor='black' cellpadding='1' cellspacing='1'>\n";
echo " <tr bgcolor='yellow'><td><b>Key</b></td><td><b>Value</b></td></tr>\n";
foreach ($keys as $key) {
echo " <tr bgcolor='white'><td>" . $key . "</td><td>" . $_SERVER[$key] . "</td></tr>\n";
}
echo "</table>\n";
Are you identifying the user at the keyboard or the device making the request? Do you need to track these long term or only for the duration of a use session? Do your users connect from multiple devices?
Client side id certificates could work, depending on how the local machines are managed. If they are accessing your app from someplace they've already authenticated, then setting up a single sign on solution could work. Prompting for authentication always works too.

Best practise to write a boolean API in Java Sturts 2 server?

I need to write an API to check if a user name already exists in a database.
I want my server (Struts Action class instance in tomcat server) to return true/false.
Its something like this
checkUserName?userName=john
I want to know what is the standard way to do this?
Shall I return a JSON response with just one boolean value ... seems like a overkill.
Shall I do something like manually setting the HTTP header to 200 or 404 (for true/false), but that seems to violate the actual purpose of using the headers which I believe must only be used to indicate network failures etc.
(Too long for a comment.)
I don't see any reason not to return a standard JSON response with something indicating whether or not the user name exists. That's what APIs do: there's nothing "overkill" about providing a response useful across clients.
To your second point: headers do a lot more than "indicate network problems". A 404 isn't a network problem, it means the requested resource doesn't exist. It is not appropriate in your case, because you're not requesting a resource: the resource is checkUserName, which does exist. If instead your request was /userByName/john a 404 would be appropriate if the user didn't exist. That's not an appropriate request in this case, because you don't want to return the user.
A 401 isn't a network problem, it's an authentication issue. A 302 isn't a network problem, it's a redirect. Etc. Using HTTP response codes is entirely appropriate, if they match your requests.

How to track unique Web request in Spring Boot?

I have a Spring Boot (MVC) java server. How can I track each unique Web request? For example, I'd like to know the following.
How to get user agent of Web request (browser type, device such as mobile or desktop)
How to get the IP address or location of the Web request?
How to count number of Web request? For examppe, I'd like to count the request count in a synchronized fashion.
Most of the things will be given by HttpServletRequest, using headers.
1. How to get user agent of Web request
User agent ? Exactly !
String userAgentInfo = request.getHeader("User-Agent");
also there is an API as utils to check the information.
2. How to get the IP address or location of the Web request?
Though I cannot point to the location information, we can get IP address information using varied headers.
X-Forwarded-For
Proxy-Client-IP
WL-Proxy-Client-IP
HTTP_X_FORWARDED_FOR
HTTP_X_FORWARDED
HTTP_X_CLUSTER_CLIENT_IP
HTTP_CLIENT_IP
HTTP_FORWARDED_FOR
HTTP_FORWARDED
HTTP_VIA
REMOTE_ADDR
Depending on the request type these can give you IP information.
3. How to count number of Web request?
Old fashioned Filter creation will help you in tracking the hit counts.
This can help you better.
If Spring-boot is the catch, the implementation is bit change in getting the values,
In the controller, using #RequestHeader(value="User-Agent") can help. Similarly for the others too.

Java HttpURLConnection | POST method | Sequence of HTTP header fields

I am trying to "spoof" a Firefox HTTP POST request in Java using java.net.HttpURLConnection.
I use Wireshark to check the HTTP headers being sent, so I have (hopefully) reliable source of information, why the Java result doesn't match the ideal situation (using Firefox).
I have set all header fields exactly to the values that Firefox sends via HTTP and noticed, that the sequence of the header fields is not the same.
The output for Firefox is like:
POST ...
**Host**
User-Agent
Accept
Accept-Language
Accept-Encoding
Referer
Connection
Content-Type
Content-Length
When I let wireshark tap off my implementation in Java, it gives me a slightly different sequence of fields:
POST...
**User-Agent**
Accept
Accept-Language
Accept-Encoding
Referer
Content-Type
Host
Connection
Content-Length
So basically, I have all the fields, just in a different order.
I have also noticed that the Host field is sent with a different value:
www.thewebsite.com (Firefox) <---> thewebsite.com (Java HttpURLConnection), although I pass on the String to httpUrlConnection.setRequestProperty with the "www."
I have not yet analyzed the byte output of Wireshark, but I know that the server is not returning the same Location in the header fields of my response.
My questions are:
(1) Is is possible to control the sequence the header fields in the request, and if yes is it possible to do using HttpURLConnection? If not, is it possible to directly control the bytes in the HTTP header using Java? [I don't own the server, so my only hope to get the POST method working is through my application pretending to be Firefox, the server is not really verbose, my only info are: Apache with PHP]
(2) Is there a way to fix the setRequestProperty() problem ("www") as described above?
(3) What else could matter? (Do I need to concern the underlying layers, TCP....?)
Thanks for any comments.
PS. I am trying to model a situation without cookies being sent, so that I can ignore the effect.
First, the order of the headers is irrelevant.
Second, in order to manually override the host header you need to set sun.net.http.allowRestrictedHeaders=true either in code
System.setProperty("sun.net.http.allowRestrictedHeaders", "true")
or at JVM start
-Dsun.net.http.allowRestrictedHeaders=true
This is a security precaution introduced by Oracle a while ago. That's because according to RFC
The Host request-header field specifies the Internet host and port
number of the resource being requested, as obtained from the original
URI given by the user or referring resource (generally an HTTP URL).
the headers order is not important. the headers got by server are also out-of-order. And you can not control httpUrlConnection header order. But if you write your own TCP client, you can control your header order. like:
clientSocket = new Socket(serverHost, serverPort);
OutputStream os = clientSocket.getOutputStream();
String send = "GET /?id=y2y HTTP/1.1\r\nConnection: keep-alive\r\nKeep-Alive: timeout=15, max=200\r\nHost: chillyc.info\r\n\r\nGET /?id=y2y HTTP/1.1\r\nConnection: keep-alive\r\nKeep-Alive: timeout=15, max=200\r\nHost: chillyc.info\r\n\r\n";
os.write(send.getBytes());
The Second question is answered by Marcel Stör in the first answer.
a
I got lucky with Apache Http Components, my guess is that the "Host" header's missing "www." made the difference, which can be set exactly as intended using Apache's HttpPost:
httpPost.setHeader("Host", "www.thewebsite.com");
The Wireshark output confirmed my suspicion. Also this time the TCP communication prior to my HTTP post looks different (client ---> server, server ---> client, client ---> server) instead of (client ---> server, server ---> client, client ---> server, client---> server).
Now I get the desired Location header value and the server is also setting the cookies. :)
For the most part, this question is resolved.
Actually I wanted to use the lightweihgt HttpUrlConnection because that's what the Android Developers blog suggesting. The System.setProperty("sun.net.http.allowRestrictedHeaders", "true") might work as well, if it allows to "www." in the Host value.

Categories

Resources