Validate request host - java

I'm developing a REST API, in some cases i want to make sure a request came from a known ip that set in a backend UI.
I tried this:
try {
URL url = new URL(allowedHostname);
InetAddress[] allowedIps = InetAddress.getAllByName(url.getHost());
for (InetAddress host : allowedIps) {
if (requesterIp.equals(host.getHostAddress())) {
return true;
}
}
} catch (UnknownHostException e) {
logger.warn("[validateHostname] ", e);
}
return false;
Where allowedHostname = request.getRemoteAddr()
But it doesn't seems to work.
i do not want just to validate the hostname, because it is relatively easy to make requests in the name of another host.
Edit
requesterIp = request.getRemoteAddr()
allowedHostname = a predefined url set in backend UI

Your serlvet container or appserver is most likely behind a proxy. To get the correct address you'll need to configure the proxy to forward the remote ip address.
http://docs.oracle.com/javaee/5/api/javax/servlet/ServletRequest.html
String getRemoteAddr()
Returns the Internet Protocol (IP) address of the client or last proxy that sent the request.

Related

simple forward proxy for any protocol

I am wanting to develop a centralized java server that accepts multiple connections for any type of network traffic IE FTP, HTTP, HTTPS, RDP, etc. The only goal is to forward it off to the expected destination and return the response back to the requester. I have no idea where to start with this because the only information I am finding is related to forwarding java servlet requests and some info on forwarding HTTP. Is there anyway to simply forward it off, or would it require handling every protocol differently?
public void run () {
InetSocketAddress address = (InetSocketAddress)this.socket.getRemoteSocketAddress();
try {
InputStreamReader isr = new InputStreamReader(this.socket.getInputStream());
BufferedReader br = new BufferedReader(isr);
OutputStream os = this.socket.getOutputStream();
String ipAddress = address.getHostName();
Log.d("client","A client has connected from: "+ipAddress);
//TODO forward the client inputstream to the destination
} catch (Exception e) {
e.printStackTrace();
} finally {
try{
this.socket.close();
} catch (Exception e) {}
}
}
Every protocol is different, unless you want to, and can, force them all into one straightjacket like HTTP's CONNECT verb. You will have to research what proxy protocols the intended clients are capable of using.
More probably you should be looking at using SOCKS, in an existing implementation.

Get IP address of client machine in Spring MVC

I have a java spring MVC web application, I am trying to get the IP address of the client machine who are accessing the application.I had tried the code shown below,
InetAddress addr = InetAddress.getLocalHost();
String ipAddr = addr.getHostAddress();
But this is returning me the IP address of localhost.
I have also tried few other suggestions found online like the one below:
String remoteAddr = "";
if (request != null) {
remoteAddr = request.getHeader("X-FORWARDED-FOR");
if (remoteAddr == null || "".equals(remoteAddr)) {
remoteAddr = request.getRemoteAddr();
}
}
This is also not giving the right IP address. I have also tried the following and nothing has worked for me:
https://www.mkyong.com/java/how-to-get-client-ip-address-in-java/
what is the right way to get request's ip
Nothing is giving me the correct IP address. Is there any solution that I could try to get the correct IP address of the machine that is accessing my application.
You have to read the request from where request is coming, Try this
public void readIp(HttpServletRequest request,HttpServletResponse response){
String ip = request.getRemoteAddr();
System.out.println("ip: "+ip);
}

Use socket programming for different android device with different network

I'm developing one socket app.
Background :
There is two android device.
Both device is on different network (i.e. one is on mobilenetwork and other is on different mobile network or on wifi).
App is working good when on same wifi network.
App is not working on different network.
I've read about port forwarding but this all ended up with router port forwarding, so this has nothing to do with my app, as my app is like to work on different network.
What I've tried:
Use Socket-communication over different networks [ Still unable to find the answer]
I got server ip address using following method and it gives me ip address:
public String getIpAddress() {
String ip = "";
try {
Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface
.getNetworkInterfaces();
while (enumNetworkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = enumNetworkInterfaces
.nextElement();
Enumeration<InetAddress> enumInetAddress = networkInterface
.getInetAddresses();
while (enumInetAddress.hasMoreElements()) {
InetAddress inetAddress = enumInetAddress.nextElement();
if (inetAddress.isSiteLocalAddress()) {
ip += "Server running at : "
+ inetAddress.getHostAddress();
}
}
}
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
ip += "Something Wrong! " + e.toString() + "\n";
}
text.setText(ip);
return ip;
}
I'm using static port 8080 [May be this is a problem,please suggest me a option if so].
I'm using this lines at client side to connect but soket object returns null on different network:
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
So,Please suggest me what should i use for communicating over
different real android device with different network [app runs on same
network perfectly]?
https://en.wikipedia.org/wiki/TCP_hole_punching
This technique can be used if you're attached to P2P connectivity.
Otherwise, you can get an online server that is accessible to both clients and it can be used to forward messages between the two. Amazon Web Services is a good option for this, you can get one year free trial with a T2.mini machine with a public IP.
https://aws.amazon.com/

Get corresponding https port number for http port in Tomcat

I'm trying to minimize the configuration for my webapp, and one of the things I want to remove is the port number mapping:
http: 80 -> https: 443
http: 9080 -> https: 9443
Since the configuration already exists in conf/server.xml, I don't want to duplicate these settings in my app. It's a pain to have to change (and remember to change) multiple config files. Also, the app should not care what environment/container it was deployed into, as long as it supports http and https.
I have the following configured in my web.xml, but I need to be able to build https URLs in addition to redirecting:
<security-constraint>
<web-resource-collection>
<web-resource-name>secure</web-resource-name>
<url-pattern>/https/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
The above block tells the servlet container to redirect http requests to its https counterpart. Obviously, Tomcat knows what connector the request came from, looks up the "redirectPort" attribute in server.xml for that connector and builds the https URL using that.
According to these previous/related questions, there doesn't seem to be a standard or tomcat-specific way of getting the corresponding https port for a request:
Tomcat: how to get the secure port number in Java?
get server name and port number of JSP page for HTTPS
TL;DR: My question is, what ideas do you have for getting the corresponding https port number for an insecure request without explicitly configuring them in your webapp?
One idea I have is to make a http call from the webapp to itself to a path behind the security constraint using the same port number as the current request and parse the redirect location from the response. The responses should be cached, of course. Is there a more straightforward way?
EDIT: Added an answer with the code for the idea.
In case anyone wanted to know how to implement the idea I offered in the question, here's some sample code I put together to test it. I don't think I'm going with this solution though.
This works with the security-constraint block from the question body.
private static final String HTTPS_CONSTRAINED_PATH = "/https";
private static ConcurrentHashMap<String, Integer> resolvedHttpsPortMap = new ConcurrentHashMap<String, Integer>();
private static final ReentrantLock portMapLock = new ReentrantLock();
public static int resolveHttpsPort(HttpServletRequest request) {
if (request.isSecure()) return request.getServerPort();
String key = request.getServerName() + ":" + request.getServerPort();
Integer port = resolvedHttpsPortMap.get(key);
if (port == null) {
portMapLock.lock();
try {
port = resolvedHttpsPortMap.get(key);
if (port == null) {
URL url = new URL(request.getScheme(), request.getServerName(), request.getServerPort(), request.getContextPath() + HTTPS_CONSTRAINED_PATH);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
if (conn.getResponseCode() != 301 && conn.getResponseCode() != 302
&& conn.getResponseCode() != 303 && conn.getResponseCode() != 307) {
throw new IllegalStateException("Got unexpected response code " + conn.getResponseCode() + " from URL: " + url);
}
String location = conn.getHeaderField("Location");
if (location == null) {
throw new IllegalStateException("Did not get a Location header in the response from URL: " + url);
}
URL locationUrl = new URL(location);
port = locationUrl.getPort();
}
} catch (Exception e) {
logger.warn("Could not determine corresponding HTTPS port for '" + key + "'", e);
} finally {
if (port == null) port = -1;
resolvedHttpsPortMap.put(key, port);
portMapLock.unlock();
}
}
return port;
}
I don't see why you need to know the secure port numbers at all. If the resource being accessed is marked as requiring SSL, Tomcat will send a redirect to https: and the appropriate secure port. That's what the configuration in server.xml is for.

I cannot get Java JMX server to bind to 127.0.0.1 only!

I have a java server. I want to be able to connect to it with a JMX client.
I do this:
JMXServiceURL jmxUrl = new JMXServiceURL(null,null,JMX_PORT);
JMXConnectorServer jmxRemoteServer;
jmxRemoteServer=JMXConnectorServerFactory.newJMXConnectorServer(jmxUrl, jmxEnvironment, server);
jmxRemoteServer.start();
This works. I can fire up JConsole and connect to JMX_PORT on my machine and pretty graphs show up.
There is a problem. This causes the JMX server to bind to JMX_PORT on all interfaces. I want to have it bind to 127.0.0.1 only. Otherwise, it is a security concern for me.
According to the documentation, JMXServiceURL jmxUrl = new JMXServiceURL(null,null,config.getJmxRemotePort()); should create a JMXServiceURL with the default protocol (jmxmp) and localhost. I have tried giving it "127.0.0.1" explicitely as an address to bind to, and it did not work either.
Java's JMX server binds to all IP addresses, and refuses to bind to 127.0.0.1 only.
Run this code:
public static void main(String args[]) {
try {
InetAddress local = InetAddress.getLocalHost();
System.out.println("Host address: " + local.getHostAddress());
System.out.println("Host name: " + local.getHostName());
System.out.println("Canonical host name: " + local.getCanonicalHostName());
System.out.println("Address: " + local.getAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
If you pass null as the host argument the class uses InetAddress.getLocalHost().getHostName(). For me at least it doesn't return "127.0.0.1", it uses my machine's name, which actually seems wrong based on the description (this is not my loopback address). That address is useable by other machines. What happens when you try:
JMXServiceURL jmxUrl = new JMXServiceURL("http","127.0.0.1",JMX_PORT);
or:
JMXServiceURL jmxUrl = new JMXServiceURL(null,"127.0.0.1",JMX_PORT);
If not supplied, the protocol defaults to "jmxmp".

Categories

Resources