6

What I need to do is running a Java application which is a RESTful service server side writtern by Restlet. And this service will be called by another app running on Google App Engine.

Because of the restriction of GAE, every http call is limited to port 80 and 443 (http and https) with HttpUrlConnection class. As a result, I have to deploy my server side application on port 80 or 443.

However, because the app is running on Ubuntu, and those ports under 1024 cannot be accessed by non-root user, then a Access Denied exception will be thrown when I run my app.

The solutions that have come into my mind includes:

  1. Changing the security policy of JRE, which is the files resides in /lib/security/java.policy, to grantjava.net.SocketPermission "*.80" "listen, connect, accept, resolve" permission。However, neither using command line to include this file or overrides the content in JRE's java.policy file, the same exception keeps coming out.

  2. try to login as a root user, however because my unfamiliarity with Unix, I don't know how to do it.

  3. another solution I haven't try is to map all calls to 80 to a higher port like 1234, then I can deploy my app on 1234 without problem, and GAE call send request to port 80. But how to connect the missing gap is still a problem.

Currently I am using a "hacking" method, which is to package the application into a jar file, and sudo running the jar file with root privilege. It works now, but definitely not appropriate in the real deployment environment.

So if anyone have any idea about the solution, thanks very much!

George Johnston
  • 31,652
  • 27
  • 127
  • 172
Yudong Li
  • 1,784
  • 2
  • 17
  • 32
  • On ubuntu you can login as root by running `sudo -i` which'll give you an interim if not ideal solution. –  Mar 15 '10 at 01:46
  • 1
    Actually, services that need to listen on ports < 1024 are usually started as root at first to get the necessary permissions. However, after having opened the ports they change their user ID to a less privileged one by doing some Unix-specific system calls. Java doesn't support that since it has to be platform independent. Yet there are some 3rd-party libs which will give you access to the Unix/Linux system API at the cost of portability. Look for "POSIX" and "Java" if you're interested in this topic. Forwarding with iptables of course is the preferable and most simple solution. – the-banana-king Mar 15 '10 at 03:48
  • @the-banana-king Thanks for your tip, and yep it is really helpful as I have never thought about doing things from Java lib to manipulate on unix systems. – Yudong Li Mar 15 '12 at 06:54
  • refer http://serverfault.com/questions/112795/how-can-i-run-a-server-on-linux-on-port-80-as-a-normal-user – Amit G May 12 '16 at 07:48

3 Answers3

7

You can use iptables to redirect using something like this:

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport http -j REDIRECT --to-ports 8080

Make the changes permanent (persist after reboot) with:

iptables-save
Jack
  • 16,506
  • 19
  • 100
  • 167
objects
  • 8,637
  • 4
  • 30
  • 38
2

Solution 1: It won't change anything, this is not a Java limitation, it's the OS that is preventing you to use privileged port numbers (ports lower than 1024).

Solution 2: Not a good idea IMO, there are good reasons to not run a process as root.

Solution 3: Use setcap or iptables. See this previous question.

Community
  • 1
  • 1
Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
1

A much easier solution is to set up a reverse proxy in Apache httpd, which Ubuntu will run for you on port 80 from /etc/init.d.

There are also ways of getting here with iptables, but I don't have recent personal experience. I've got such a proxy running right now.

bmargulies
  • 97,814
  • 39
  • 186
  • 310