15

I want to restrict access to certain URLs in my Tomcat webapp. Only 3 known IP addresses should be allowed access to URLs that fit a certain pattern.

e.g. http://example.com:1234/abc/personId

How can I achieve this?

Mark Thomas
  • 16,339
  • 1
  • 39
  • 60
Randeep
  • 533
  • 3
  • 7
  • 18
  • 1
    How are you deciding whether to deny or permit access? By IP? By logged in user? By geographical region? Why do you have iptables in there? iptables is not aware of a URL that may be in use. What stack is running your web server and at which point in your network architecture do you wish to deny access? – Cheekysoft May 08 '12 at 12:06
  • It's really not clear what you're asking about. Is this machine a web server and you're trying to restrict access to URLs it serves? Or is this machine a NAT box? Or reverse proxy? – David Schwartz May 08 '12 at 12:06
  • by ip. I have three ips from only I need the access. I want to ban all other ips from using the api. – Randeep May 08 '12 at 12:08
  • System is centos and I'm using apache and tomcat. iptables is there in it. – Randeep May 08 '12 at 12:09
  • @Cheekysoft Actually my site provides information to some apps. But there are a few api I need to ban from public access. http://example.com:1234/abc/(personId) like this. – Randeep May 08 '12 at 12:12
  • @DavidSchwartz Yes. This is a webserver. Yes I want to deny some of the api urls it serves from public. – Randeep May 08 '12 at 12:14
  • Then do it in the configuration for the web server software. – David Schwartz May 08 '12 at 12:21

4 Answers4

12

Use org.apache.catalina.filters.RemoteAddrFilter and map it to the URL you wish to protect. See http://tomcat.apache.org/tomcat-7.0-doc/config/filter.html#Remote_Address_Filter for configuration details.

Mark Thomas
  • 16,339
  • 1
  • 39
  • 60
  • my url starts with a port! its not working for me. I added the following lines in server.xml Remote Address Filter org.apache.catalina.filters.RemoteAddrFilter allow 122\.167\.211\.31 ##my ip Remote Address Filter /abc/* ## for http://example.com:1234/abc/(personId) – Randeep May 08 '12 at 14:24
  • 1
    Filters aren't defined in server.xml, they are defined in web.xml. Treat it as a normal servlet filter. – Mark Thomas May 08 '12 at 14:42
  • Sorry, but your url starts with a port???? And this port is not the tomcat port?? How your api is running on tomcat? – Plínio Pantaleão May 09 '12 at 12:21
  • Yes. It is an another application which listens on 1024. I just gave an example url in the question. it directs traffic to tomcat. But the thing is there is no filter option in tomcat 6. that is why this is not working. :( – Randeep May 09 '12 at 13:27
  • In Tomcat 6 you can use the equivalent Valve: http://tomcat.apache.org/tomcat-6.0-doc/config/valve.html#Remote_Address_Filter – Mark Thomas Aug 30 '13 at 10:10
4

You can do that with this in server.xml:

 <Valve
    className="org.apache.catalina.valves.RemoteAddrValve"
        deny="117.40.83.*,122.224.95.*,119.255.28.*,218.8.245.*,218.85.139.*,219.117.197.*,124.89.39.*,58.18.172.*,180.153.225.*"
        />

(these are real IP addresses: owners, you know why :-|) but as you can see it is really a blocker not an enabler. A better solution would be to put Apache HTTPD in front of it with Deny All and Allow From statements, which will let you allow only the 3 IP addresses you need to access the service.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • You can only add Valves to Container elements (Engine, Host, Context). You can restrict them to a subset of URLs within an application. For that, you need the Filter version. – Mark Thomas May 08 '12 at 12:30
  • Worth noting this answer relates to Tomcat 6. In Tomcat 7 the syntax has changed, as the whole entry is a regex. – Chris Haines Jan 09 '13 at 11:28
3

You can use something like this to block ips and if you are behind proxy:

<Context path="/manager" docBase="manager" reloadable="true" privileged="true" >
  <Valve className="org.apache.catalina.valves.RemoteIpValve"/>
  <Valve className="org.apache.catalina.valves.RemoteHostValve" allow="<your IP regex>"/>
</Context>
j0k
  • 22,600
  • 28
  • 79
  • 90
The-Bat
  • 31
  • 1
0

I wouldn't restrict access by IP address, for the following reasons:

  • Doing so on say internal addresses, e.g. 10.0.0.0/24, means you implicitly trust this entire range. What happens if it is compromised?
  • Not all of your customers can or will be able to get static IP addresses - assuming you might want to allow some customers access.
  • Customers behind gateway devices where proxies do not support x-forwarded-for headers are going to just have the IP of the gateway device; trusting that IP trusts everyone behind the gateway, again assuming you might want to give some customers access.

Instead, if you need to run a system where some calls are only accessible to certain users, I'd use authentication - SSL client side certificates work quite well for this purpose. Alternatively, you could use something like OAuth.

  • Thanks for your reply. The thing is my server is providing information to mobile apps. So I have a lot of public api's. I cant block them from public. But there are some private api's also. That should be only accessed from three internal systems. And I cannot add additional authentication mechanisms. – Randeep May 08 '12 at 12:22