Hiding Jamf Pro's Admin Interface Externally In A Single Tomcat Server Setup

In some Jamf environments the Tomcat webapp might need to be hosted on a single machine that is both accessible from inside an organization as well as externally on the public internet.

But what if you don’t want the Jamf admin console visible to the external world but still want to allow your clients to check in, enroll, or access the API? If you were in a clustered environment you could easily change the Limited Access settings for your externally facing webapp to something other than “Full Access”, but this isn’t possible on a single server setup.

At our org I found myself in this situation with a development Jamf server that I wanted to be available both internally and externally but only use one server in AWS to keep costs reasonable. The server would be behind an AWS load balancer which would handle HTTPS termination and limit exposure to the outside world.

I decided the most obvious way to determine an internal machine vs an external one would be based on IP address. So, is it possible to filter connections to Tomcat based on IP? It is! To accomplish this we need to use a Tomcat filter.

Two caveats: This has only been run in production with Jamf Pro 9.x though it seems to work fine with version 10.x with some slight modifications which I’ll note below. Also these modifications can be overwritten during Jamf Pro updates so you will need to reapply them each time.

Tomcat provides many filtering options but the one we want is “Remote Address Filter” which according to the documention:

“allows you to compare the IP address of the client that submitted this request against one or more regular expressions, and either allow the request to continue or refuse to process the request from this client.”

For this to work we need a regular expression that will match any IPs in the standard private IP ranges of:

  • 10.0.0.0 to 10.255.255.255
  • 172.16.0.0 to 172.31.255.255
  • 192.168.0.0 to 192.168.255.255

I wrote this simple regex that should capture all those IP addresses.

Next we need to pair the regex with a Tomcat filter that is set to accept connections from IPs that are matched:

Use this for Jamf Pro version 9.x:

Use this for Jamf Pro version 10.x

You’ll then need to insert that xml into the webapp’s web.xml file (including after every upgrade) at /usr/local/jss/tomcat/webapps/ROOT/WEB-INF/web.xml

Stop Tomcat and place the filter xml code in the file. In my case I inserted it under this section in the file (for both v9 and v10):

1
2
3
4
<servlet-mapping>
<servlet-name>LegacyRestRedirectServlet</servlet-name>
<url-pattern>*.rest</url-pattern>
</servlet-mapping>

Restart Tomcat and try to hit your Jamf Pro’s server from a public IP:

Awesome! But wait…the default Tomcat error page is not great and it’s also showing what version of Tomcat we are running which could give someone looking to exploit known weaknesses in certain versions of Tomcat an easier time of discovering if we are vulnerable. (Hat tip to Ross Derewianko who pointed out this security issue to me a while back.)

Luckily we can set a custom 404 page in Tomcat for this. It’ll just take a bit of extra work.

First, we’ll need to create an error page and place it at the root of our Tomcat webapp at /usr/local/jss/tomcat/webapps/ROOT/, and for this example I will call it 404.jsp

Next, we’ll need to tell Tomcat that we want to use the 404.jsp file as the 404 page when someone tries to reach our admin console from a denied IP address. To do this we’ll need to edit a different web.xml file, which can be found at: /usr/local/jss/tomcat/conf/web.xml

Edit this file and search for welcome-file-list and beneath this section, add:

With that done, now restart Tomcat, and when you try to visit the admin login from a denied IP address, you should no longer see the generic Tomcat error page but the one you just created.

Share Comments