I added a static DNS entry into my router, binding some IP address to builds-mac. I then attempted to look up its IP address using Java:
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Testcase
{
public static void main(String[] args) throws UnknownHostException
{
System.out.println("got: " + InetAddress.getByName("builds-mac"));
}
}
This failed with:
java.net.UnknownHostException: builds-mac
at java.net.Inet4AddressImpl.lookupAllHostAddr(Native Method)
at java.net.InetAddress$1.lookupAllHostAddr(InetAddress.java:901)
at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1293)
at java.net.InetAddress.getAllByName0(InetAddress.java:1246)
at java.net.InetAddress.getAllByName(InetAddress.java:1162)
at java.net.InetAddress.getAllByName(InetAddress.java:1098)
at java.net.InetAddress.getByName(InetAddress.java:1048)
but when I replaced the hostname with builds.home.local (updating the DNS entry accordingly) then the operation succeeded.
Why does InetAddress.getByName() require a hostname suffix? Is it possible to make it work for hostnames without a suffix?
(I am running JDK 1.7.0_60 under Windows7, 64-bit)
UPDATE: nslookup builds-mac always works whereas initially ping builds-mac fails (could not find builds-mac) but then when I launch the virtual machine in VMWare, ping begins to work. Once ping begins to work, so does InetAddress.getByName().
Why would ping fail to find a host when nslookup does?
Why would launching the VM cause ping to begin seeing the host? Remember, ping says could not find builds-mac as opposed to finding the host but not getting any response because the host is down. The latter is expected, but the former is not.
UPDATE2: So, I've discovered three more interesting clues...
Whenever ping works so does InetAddress.getByName(). This is not the case for nslookup.
By default, routers are not assigned a domain name. In this mode, nslookup always works but ping does not.
If I assign the router a domain name and renew [1] the lease of the computer doing the lookup, then ping begins to work.
[1] Rebooting the computer or running ipconfig /renew picks up the new domain name, but ipconfig /flushdns does not.
So, this brings us back to the original question:
Why does the Windows Client Resolver (what ping uses under the hood) require a domain name suffix? I mean, shouldn't it work even without one?
Related
If I use this solution:
new ServerSocket(9090, 0, InetAddress.getByName("localhost"))
...and the user changes it's system hosts file to access my website as "localhost", will this fail to prevent access from non-local client?
(in response to the bounty call)
As always in computer security, guarantee depens on attacker capabilities.
The attacker is lame and knows nothing. Then yes, localhost guarantees the locality of the client.
The attacker has login access to the system and can run SSH to the outer world. Then no guarantees - SSH can forward internal ports through tunnels:
ssh -R *:8080:localhost:9090 some.external.server
Executing this command on the box with your java server will result in establishing a tunnel. All requests addressed to some.external.server:8080 will be delivered to localhost:9090 of the target box.
VPS nowdays costs almost nothing, so the attacker can easily rent such external box and use it as the proxy between your localhost and the whole world.
You may try to protect your server by filtering out all requests where Host header is not localhost. It could be easily countermeasured by including a header-rewriting proxy, such as nginx, to the forwarding chain.
Summary
As you can see, guarantee means that users in the target box must be severely limited: no forwarding software. It implies denying users access to system utilities like ssh or installing and/or running them with user privileges. This is highly unlikely unless the box is a set-top box without any user login or software reconfiguration.
Localhost address
The first comment to the question suggests a trick with localhost name resolution:
the user could probably override localhost to that it's no longer 127.0.0.1
The idea is to place a record to /etc/hosts or c:\Windows\System32\Drivers\etc\hosts that binds localhost name to another IP address.
If your box has an Ethernet connection with, say, address 1.2.3.4, then the line
1.2.3.4 localhost
might cause change of localhost address. If this happens, then the line
new ServerSocket(9090, 0, InetAddress.getByName("localhost"))
will bind the port 9090 on the external network interface, that is accessible from the outside of the box.
I tried this on Ubuntu 18.04, and it worked. I successfully connected to the app running on localhost in the box on the other side of Pasific.
BUT
Once upon a time MS Windows developers hardcoded localhost to be 127.0.0.1. Here is the Medium post about that.
I checked with my Windows 10 box. Confirmed: localhost resolves to 127.0.0.1. The test program
package org.example;
import java.net.*;
import java.io.*;
public class TryLocalhost {
public static void main(String[] args) throws IOException {
System.out.println("localhost: " + InetAddress.getByName("localhost"));
}
}
produces
localhost: localhost/127.0.0.1
while hosts file tried to bind localhost to the link-local address
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
192.168.0.198 localhost
The comment is original, from Microsoft.
I have a java process running (on java 7) on some remote server that I want to monitor using Java Mission Control. However, JMC is unable to connect, although I can telnet to the server using the port jmx remote port (12345 here, see below).
The remote java proces is started with
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.port=12345
-Djava.rmi.server.hostname=<some ip address>
-Dcom.sun.management.jmxremote.authenticate=false
and these seem to be correct values to me. Port 12345 has been opened on the firewall, but I suspect that the rmi server port is blocked by the firewall.
Thus, my question is: Is there any way (using netstat on the server or maybe even telnet from the client) to determine which rmi server port the java process is currently using on the server? (Using netstat, I see several ports being used by the java process. However, I don't have a clue which one is the rmi port.)
Adding '-Dcom.sun.management.jmxremote.rmi.port=12345' could help
See Why Java opens 3 ports when JMX is configured?
This should display where a JMX remote client is told to connect to (plus some internal info) possibly after timing out:
//nopackage -- move if you like
import java.rmi.Remote;
import java.rmi.registry.*;
import java.rmi.server.*;
import sun.rmi.server.UnicastRef;
import sun.rmi.transport.LiveRef;
public class JMXTarget {
/*
* run: java JMXTarget host port
* where host (name or address) contains the JVM process offering JMX
* and port (number) is the registry specified by -Dcom.sun.management.jmxremote.port
*/
public static void main(String[] args) throws Exception {
Registry reg = LocateRegistry.getRegistry (args[0], Integer.parseInt(args[1]));
Remote r = reg.lookup ("jmxrmi");
RemoteObject ro = (RemoteObject)r;
RemoteRef rr = ro.getRef();
UnicastRef ur = (UnicastRef)rr;
LiveRef lr = ur.getLiveRef();
System.out.println (lr);
}
}
Note if sysprop java.rmi.server.hostname is specified as you did, its value (your "some ip address") is where the client connects. If that value is not an address of the target machine, or a name that resolves (for the client) to an address of the target machine, it won't connect. If you don't specify it, it defaults to (edit) the value determined by InetAddress.getLocalHost() which is or at least should be a valid address for that machine.
I'm in need to develop a java library which allows a traffic to be directed via proxy only for specified hosts.
The library is almost ready and working, but there is problem with resolving dns addresses via proxy.
In short words I extended CustomProxySelector class which has following logic:
public class CustomProxySelector extends ProxySelector {
public List<Proxy> select(URI uri) {
if (customProxyDefinedFor(uri)) {
return getCustomProxyFor(uri);
} else {
// use direct connection
}
}
}
All works fine if local dns can resolve host given as "uri" parameter (for example if I want stackoverflow.com to go via proxy it will work because my local dns can resolve stackoverflow.com).
The problem comes when there is a host which is not known to my local dns. For example the dns behind proxy knows how to resolve address like "host1.private.dmz" because this is special host only known behind proxy (the proxy acts really as reverse proxy here). JVM seems to first try to resolve "host1.private.dmz" to ip, and when it fails it ends with folowing stacktrace:
Caused by: java.net.UnknownHostException: host1.private.dmz
at java.net.InetAddress.getAllByName0(InetAddress.java:1259)
at java.net.InetAddress.getAllByName(InetAddress.java:1171)
at java.net.InetAddress.getAllByName(InetAddress.java:1105)
at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:247)
(...)
Because it fails to resolve the ip, my Custom ProxySelector is never used. Is there any option to force java not to resolve ip via localdns but via proxy?
If I give the ip address of host1.private.dmz (for example 10.100.12.13) all works ok. The communication is directed to my Custom Proxy Selector and the traffic goes via custom proxy without problem.
I solved this issue. The important thing to fix this problem is correct understanding that the problem does not lay in jvm but in application. Jvm does not try to resolve host1.private.dmz before calling custom proxy selector, it is the application itself.
If we have a look at last line of the stacktrace you can see that exception comes from mysql jdbc driver, so it is mysql driver who trys to resolve host1.private.dmz to IP address, before actually opening connection to that host. Therefore because application does not open a connection (because exception occurs when application trys to resolve dns), no proxy selector is called ("no connection" == "no proxy selector").
What can we do in such case?
If it is you who writes the application, simply don't resolve the IP by calling InetAddress.getAllByName() and directly open connection to host domain name (host1.private.dmz). If for some reason you need an IP than handle the exception (in case of exception try to open connection without resolving the address). If still this is not acceptable for you there is one more option. You can instruct jvm to use extra DNS server which is able to resolve IP of this domain. You can do this by setting following properties:
System.setProperty("sun.net.spi.nameservice.provider.1", "dns,sun");
System.setProperty("sun.net.spi.nameservice.nameservers", "10.200.2.3,100.40.70.5);
This should set extra dns server for your application.
There can however be one more problematic situation. An attempt to resolve domain name to ip might take place before you have the chance to set up extra dns servers. For example you might be running web application on Tomcat with database connection pool configured in Tomcat's context. In such case the exception "UnknownHostException" can happen before you set up extra dnses. In such case you can run this application by "proxifying it". Strictly in java you can do this by using jProxyLoader library (http://jproxyloader.sourceforge.net) , for example by running the application with following parameters:
-Djava.system.class.loader=net.sf.jproxyloader.JProxyLoader -DjplDnsServers=10.0.1.18
Above example will set up 10.0.1.18 as extra dns server (which is able to resolve the uknown domain name) at application startup. Thanks to this extra dns will already be available when application boots up.
You understand more about this problem, by having a look at jProxyLoader troubleshooting page: http://jproxyloader.sourceforge.net/troubleshooting.html
i have one server installed in my system.It takes one of the ip addresses and acts as own system.
In my java program i connect to that server using the following code.
ServiceInstance si = new ServiceInstance(new URL("https://10.100.13.36/sdk"), "user", "password", true);
true indicates the ignore certificate to be true.
when i tried to execute with false parameter it says the following error.
CertificateException: No subject alternative names matching IP address 10.100.13.36 found
i got here that i have to use the dns name instead of ip address in case of certificate mode of server.
So i found in the server configuration settings that the server is taking the DNS name as localhost.localdomain
so i tried with the url as https://localhost.localdomain/sdk
it has shown the error that localhost.locadomain has not been found.
i guess it has some problem with DNS name resolution with localhost as my system and localhost.localdomain as my server dns name.
can we find the dns name with giving ip address through java program.So that it finds the DNS name on its own and pass the value in the url.
can anybody give some suggestion on this.
Thank you..
A DNS name is assigned by your local DNS server. The name localhost.localdomain is usually assigned in the host file so various local operations function (e.g., system logging, sending email to the root user from periodic tasks). I would guess that your server is not registered in the local DNS server. It is rare that locally run virtual machines actually have a valid registration in DNS - this is especially true for Linux systems running in a Windows environment.
If it were registered in DNS and both your server and client were using the same DNS hierarchy, then all that you need to do is create an java.net.InetAddress using the IP address of the machine and call getCanonicalHostName() to retrieve its DNS name. If it does not have a name registered in the local DNS server, then you will simply get the IP address back.
I am trying to create a WebService. I am not able to access the URL. If I try to connect to
http://192.168.10.203:8080/EchoBeanService/EchoBean?wsdl
I get an error:
Firefox can't establish a connection to the server at 192.168.10.203:8080
However, if I am able to connect to the using localhost in the URL:
http://localhost:8080/EchoBeanService/EchoBean?wsdl
Echo.java
package services;
public interface Echo {
public String printEcho();
public String printEchoParam(String str);
}
EchoBean.java
package model;
import javax.jws.WebService;
import javax.ejb.Stateless;
import javax.jws.WebMethod;
import services.Echo;
#Stateless
#WebService
public class EchoBean implements Echo {
public EchoBean(){}
#WebMethod
public String printEcho(){
return "WebServices Echo ";
}
#WebMethod
public String printEchoParam(String str){
return ("In PrintEcho( String " + str +" )" );
}
}
-H
I have absolutely no knowledge of java, but this symptom doesn't seem all that unique to web services in general. Maybe something to do with either this java app or the server by default binding only to or listening at localhost:8080? Maybe this would help to change that: How to change webservice url endpoint?
Similar instructions, specifically the 'Deploying the Web Service' section: http://today.java.net/article/2006/06/12/web-services-made-easy-jax-ws-20
Otherwise, like folks said above: check your local firewall to see if incoming connections are blocked, or verify the IP addressed assigned to the system this service is running on.
Check the following:
Is 192.168.10.203 your IP address?
Do you have any firewall on the appropriate network interface (the interface of 192.168.10.203), that might block the connection?
Also some application servers disable remote connections by default for security reasons. Your server might have to be setup to allow remote connections.
You can check network connectivity by using telnet to connect to the port.
telnet 192.168.10.203 8080
If you are running on Linux you might be blocked by IPTABLE. Try to disable that and see if you can connect from your remote IP/Hostname.
Either way it seems like a firewall issues or incorrect IP address.
Look up your IP Address with ifconfig (unix based) or ipconfig (win)
If this is a home network, I know that some routers/modems don't like looping back to themselves (I have seen this behavior with linksys devices). But localhost still works, because the OS catches it before it goes out to the network appliance. Have you tried connecting to any other ports on your machine, or just doing a ping of the IP address to see if it responds?
Thank you all,
Resolved the issue by reinstalling my glassfish server.