I'm writing a Java application like AIM where I want a lookup server to help two clients connect to each other with the ServerSocket class. Unfortunately a serversocket needs an open port or it will be blocked by your firewall. Without having the clients manually change their firewall settings is there a way I can either find an open port, open a port (it's okay if it asks for permission) I just don't want every client to manually have to change firewall settings. Thanks!
Creating a ServerSocket is what opens the port on the server end (assuming the port is NOT also blocked on the firewall). On many systems, port numbers <1024 are not blocked by the firewall, and therefore often don't require custom configuration. However, since many ISPs have been more and more stringent with what ports they block within their network, many pieces of software have moved to operating over port 80. Why port 80? It's the port used for HTTP, and therefore pretty much open (at firewalls) 100% of the time for any service that operates on the web.
To answer the question of how to find an open port, port scanners perform this function. Basically all they do is try to establish a connection on a range of ports (say port 1-1024). When a connection is successful (in Java you would see this as a good connection over a Socket), you can consider that port "open". You don't need to exchange any data in order to make the connection, you just need to establish the connection, and then close it.
Also, if there is no server software of any kind running on the server, it won't appear "open", even if it isn't blocked. Without a successful Socket (TCP) connection, you won't know what ports are not blocked by user's firewall.
To reiterate, I'm switching back and forth between two related, but separate concepts. Firewalls can block/open ports, or have port forwarding. That's not the same as a port being "open" for connections on a given machine. In order for a machine to accept connections on a given port, there must be a piece of software listening for a connection on that port, otherwise no connection can be made.
I would suggest to look at a couple of alternative solutions that are less cumbersome - scanning for open ports can take quite some time, can cause panicky reactions from firewalls that feel attacked, and so on. There are a couple of techniques that are in active use and have been developed exactly to solve the problem of servers behind firewalls.
UDP Hole Punching, zero user side configuration needed. Simple explanation on how Skype uses this technique can be found here
UPnP / IGD could be used as an alternative, though less devices support it out of the box nowadays due to security problems.
STUN with a Java implementation of client and serverside called JSTUN
Whatever solution you choose, test it thoroughly with different internet service providers, there's a plethora of limitations you can expect wrt blocked ports.
Related
The problem: In java you can create a socket on the server with ServerSocket(0) and it will choose a random port to listen on. However when you create a socket on the client to send a message with Socket(addr, port) there is no apparent way to determine which port on the server you need to send to. I couldn't find anything about this option through web searches besides the basic "if you put 0 it will chose a random port". Does anyone know or have a resource that could explain what this scenario is supposed to look like from the client end?
Some background: I am currently converting a system from UDP to TCP. The reason I need the server to listen on a random port is that my server/client do not have a strict server/client relationship. So the "server" in this situation is really an application that I need to open multiple instances of on one PC. The old way of having predetermined send/receive ports is causing only one instance to be able to open a port and all communication is being redirected to that instance. My understanding that the best way to fix this problem is for each instance to use a different port, and the best way for that is to do ServerSocket(0). Despite including this background, I do not want comments on how messed up the situation is, only answers pertaining to the problem.
If a fixed port number is not part of the server's documented setup / protocol, then the only way for clients to figure out is to have the running/active servers publish that information in some datastore, the location and details of which are documented and known by the clients, and where that datastore is reachable for the clients.
[Or have the clients run a portscan each time they want to connect. It will work but probably not as fast as your users would like.]
And your situation is indeed messed up.
Perhaps if you are on the same IP subnet with all the servers/clients, then you could use UPnP to signal which random port new instances of your application are running on, and similarly other instances could monitor UPnP to discover this new instance.
I've never implemented UPnP in Java, but suspect libraries are out there..
eg. https://github.com/jupnp/jupnp
I am doing an android app allowing users to play online.
Currently, I use a TCP server: when two persons are connected, the server takes care of forwarding the packets between the two clients.
I would like to replace my server by a java servlet with google app engine. This new server will just be used to connect the two players.
It would work in that way:
Player A opens a server socket and then post to the server the connection details.
When a player B wants to play against A, he asks to the server the port number of A and he connects directly to A.
The problem is that I am not sure that it will work if player A is behind a NAT. When player A opens a server socket, that opens one port of its 192.168.x.y address, but does it ask to the box a port forwarding? I assume it doesn't...
So two questions:
Is it possible to make a direct connection TCP between two devices even when there is a NAT or a firewall (I don't know how firewalls work on Android...)
If it isn't possible, what is the best solution: Is it possible to make a TCP server to ensure the exchange of the messages with app engine?
Thank you by advance.
game
Creating direct TCP connection between users under different NAT is mostly possible. There are 4 types of NAT. FC, ARC, PRC, Symmetric. If one of player A or B has symmetric NAT then it is impossible to create TCP P2P connection. In this case you will have to use a server in the middle for exchanging data between two players.
For other types of NAT combinations it is very much possible but not guaranteed. The technique that is used to create TCP P2P connection is called TCP hole punching. Read this answer to know in details about this technique.
Also creating TCP P2P connection is not related to any platform.
First, the device itself is probably not going to be the main problem. If they are at home and using WiFi, you will probably have to deal with a cable modem/DSL modem, which typically includes a firewall. Also if they are at work (or a hotel, conference center, etc.), there may be a corporate firewall to deal with.
I believe most home cable/DSL modems support uPnP (Universal Plug and Play), which includes the Internet Gateway Device Protocol (IGD) designed to let devices determine the external IP address and set up port mappings. In general you can look up NAT traversal for ways to handle connections through a home modem/firewall. I will note that corporate firewalls are a different matter and many of these techniques won't work.
So probably I would recommend you be ready for at least the following four scenarios
Direct connection with nothing creating problems. You can test this by having the server do a test connection when the player first contacts the server. If this works, things are simple.
Home NAT device that understands uPnP. If you have a 10.x.x.x, 172.16.x.x-172.31.x.x, or 192.168.x.x number (typical home WiFi), then you can try to set up the NAT traversal and if that works you can send the appropriate information to your server. It probably would be worthwhile for the server to do a test connection just to be sure that things work.
If you have a firewall that you can't get around, then make a note on the server regarding player A, and when B tries to join A's game, look and see if B will accept connections, and if so then arrange for A to connect to B instead.
If none of the above work, then have A and B both connect to the server and have the server relay messages between A and B.
If you don't want to program all those possibilities, then option 4 is the one that is most likely to work, even if it does mean extra traffic going to/from your server. But note that for corporate networks, they may simply have a rule blocking unknown connections, and there may not be much you can do.
Edit: I was able to get a simple TCP server working on Android without anything special regarding Android itself, so removed a comment saying I didn't know about that.
First of all, i am a newbie in network programming. Few days ago, i wanted to test a simple java server(simple java echo server). I first tried running it in a university computer and then tried connecting through my laptop which is in a different network without any success. I assumed the network(private university network) didn't allow the connection. Next, i ran the server in my laptop expecting it to be public. I ran the server. I ran it in port 5000. Since the connection was through wifi i also did port forwarding so that my router would know where to forward the incoming requests. I even disabled the firewall just to test. Then there is a tool in the internet which i obtained from some other user in stackoverflow http://www.yougetsignal.com/tools/open-ports/ which can check if a port is open in a machine. I put my ipaddress and port number to see if it is reachable. It continued saying the port is closed. Although i don't have a good idea about networks, i called the ISP and asked if the issue was with the network being a private network and if it is possible to host server in my laptop, she concurred saying it was private network and what i am trying to do is not possible. I wanted to try it in some other computer. I met one good guy in stackoverflow who allowed me to run the server in his computer in taiwan. He disabled his firewall or added an exception, then ran the server. I then ran my client and it could successfully connect to his server. I was ecstatic.
So, my question and curiosity is how does isp blocking incoming connection work? Did the ISP really block the incoming connection to my server or could the problem be with some other things? Is it ever possible to host server in my laptop which is accessible to the world. I am still not content with the answer i got from the ISP which was it was private network so it was blocking..isn't internet basically the collection of private networks connected to each other so isn't everyone in one way or other part of a private network? Please help me with these dilemmas. Appreciate your effort and help a lot! :)
Your house probably has one global external IP assigned to you by your ISP. They will normally block commonly used ports incoming, such as 80 (HTTP), 22 (SSH), 23 (Telnet), 25 (SMTP), and 443 (HTTPS). The majority of the remaining ports should be open for you to use.
As you have one global IP, and multiple devices on your network, you need to tell your router which computer the incoming traffic on a given port needs to go to. This is called Port Forwarding. As you don't control the routers upstream from you at your university, you can't change anything while there. At home you can.
Port Forwarding is explained in depth here.
I suppose it depends on the ISP. I have been able to open ports before with mine, using port forwarding from my router.
As a technician who works for an ISP, I can also say that the tech support generally doesn't have a clue whenbit comes to port blocking or networking in general, they mostly follow a script and ask you if you have turned it off and on again. Maybe check that you are forwarding the port correctly?
I have a application which listens for commands over IP.
The program works fine locally but when I try to send the application commands with a remote address it won't connect.
Is there anyway to get around the router blocking the inbound network traffic?
I'm using JAVA
Thanks.
If this is a pair of hosts you control, you can open the incoming port. You might also
succeed using a tunneling program such as Hamachi to effectively set up a VPN linking
the hosts.
If you're talking about a pair of unrelated computers (for example trying to set up
a connection for a game) there's no general solution that doesn't involve installing
and trusting additional software. The usual solution is to use a public server and
relay the traffic between the end points.
I created a small chat program, that works flawlessly when client & server are run on the same computer (and probably network, too).
However, as soon as I try to connect to another computer over the internet, the socket connection simply times out.
Is this because of firewalls / routers, etc?
And how can I connect a ServerSocket & Socket over the internet?
However, as soon as I try to connect to another computer over the internet, the socket connection simply times out. Is this because of firewalls / routers, etc?
Yes, most likely. You're running into the NAT problem: essentially, the same externally visible IP address maps to many internally visible endpoints, and external endpoint doesn't know which internal endpoint to give your socket request to.
The easiest way around this is to have both your clients connect to a third party which both of them can see, and then have the third party mediate the communication. This is how most instant-messaging protocols work, for example.
If you have no way to control a third-party entity like that, an alternative to directly connect two clients is to have both clients open up an agreed-upon port, and then map communications on that port to their own internal endpoint. This provides the missing link that the externally visible endpoint (e.g. your home router) needs to deliver the communication to its intended destination.
If your server is behind a NAT router box (and most home computers are, especially if you use WiFi), then it won't be reachable from the outside unless you set up your router to port forward to that server.
What's the IP of your server computer? If it's 192.168.x.x or 10.x.x.x, then it's a non-routable address and can't be reached from outside.
Assuming with running on the same computer you mean that you tell the client the server is at 127.0.0.1 / localhost, it shouldn't be a problem in your code but because of firewalls or routers. If your server is behind a router performing masquerading (i.e., the server doesn't have a public but private IP address like 192.168.x.y for instance), you have to configure the router to pass a connection from the internet to the computer running the server.
Another reason why it doesn't work might be the way you bind your server to the interface. If you specify 127.0.0.1 there, the server will only listen for requests coming from the same system. If you don't specify an address, it will listen on all interfaces.
Edit Your comment indicates that you indeed have the NAT problem like others said. Configuring your router accordingly is probably the easiest solution.
First, test to see if it really works on a LAN; it sounds like you're just assuming it does.
If it works on your local network, perhaps it's failing because the server lacks a public IP, and is running behind a NAT'ing router.