Tomcat: An IPv6 Address Filtering Gotcha

This is another in my series of short posts covering my efforts to stand up a Tomcat/ACF10 development environment. For background, see the first post in the series.

In my previous post, I revisited allowing access to pages served up by Tomcat to just requests originating from the local system. In that post, we looked at use of Tomcat’s Remote Address Filter in order to have any denied requests be provided with a custom error page. As I noted, however, when I tried to access my Tomcat server via an IPv6-based URI (e.g., http://[::1]:8501/test.cfm), my request was being denied even though I had configured the filter to allow access to requests from the following addresses (specified via regex):

  • 127\.\d+\.\d+\.\d+
  • ::1
  • 0:0:0:0:0:0:0:1

Given the second and third of those address specifications, I would have expected my request to have been allowed. This is where having access logs configured comes in handy. Those logs showed these requests coming from 0:0:0:0:0:0:0:1%0 and being denied. OK… what’s with that trailing “%0”?

A bit of digging and I had my answer: the IPv6 address specification includes something called “scopes” that may be present. That “%0” is the default scope and (as the default) is optional. The RFC for these scopes is pretty fuzzy, so for now will allow for an optional non-negative decimal integer for the scope (per the RFC) and if we ever end up with something else (which the RFC indicates is possible) we will revisit this. We will update our regexes to account for the possible presence of the scope:

  • 127\.\d+\.\d+\.\d+
  • ::1(%\d+)?
  • 0:0:0:0:0:0:0:1(%\d+)?

Update the list of address regexes in the filter definition, bounce the server, and Tomcat should now allow requests when invoked with an IPv6-based URI. Now we can get back to looking at the extent to which ACF10 supports IPv6.

A final thought on this: you may or may not encounter this, as I have the distinct impression this behavior is a function of the environment (at least the OS and/or the JDK under Tomcat). I’ve blogged it simply because I tripped over it.

Tomcat: Revisiting IP Access Restriction

This is another in my series of short posts on configuring Tomcat as I get a Tomcat/ACF10 development environment configured. For a bit of background, see the first post in the series.

We took a quick look earlier at restricting access to my Tomcat server based on the IP address from which the request originated. In that first take, we used Tomcat’s Remote Address Valve component to restrict access to just requests from the local system. In that post, I indicated we would probably look at this subject again in the future. Here’s my second look… and I know we have at least one more coming.

One of the first items I plan on digging into with ACF10 is how it deals with IPv6. As I started poking around the edges of this, I discovered two things that merited further investigation:

  1. Requests to my local server with an IPv6-based URI (e.g., http://[::1]:8501/sample.cfm) were being blocked despite the inclusion of the IPv6 versions of the local server address (i.e., ::1 and 0:0:0:0:0:0:0:1) in our earlier Valve-based set of allowed addresses, and
  2. I was not seeing my custom 403 error page that I expected, based on my earlier work to configure one

To figure out what’s going on with the second of those two items, let’s look at where the addressed-based restrictions were implemented vs. where the custom error pages were configured:

  • My Valve-based address restrictions were implemented within the Host element in ./cfusion/runtime/conf/server.xml
  • My custom error pages were configured in the web-app element within ./WEB-INF/web.xml

It’s not too big a leap to see that the two items are configured at two different levels within the overall configuration of Tomcat and the ColdFusion Web application. This is one of those places I’ve bumped into the “there is more than one way to get there” aspect of Tomcat. Tomcat also provides a Remote Address Filter which provides the same functionality as the valve we used in our first run at this. As a filter, it is configured for the Web application (i.e., at the same level as our custom error pages) so it made sense this might address problem #2 from above.

Add the following filter specification to ./WEB-INF/web.xml as the first filter:

<filter>
   <filter-name>Remote Address Filter</filter-name>
   <filter-class>org.apache.catalina.filters.RemoteAddrFilter</filter-class>
   <init-param>
      <param-name>allow</param-name>
      <param-value>127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1</param-value>
   </init-param>
</filter>
...

Add the following filter-mapping specification to the same file as the first such mapping:

<filter-mapping>
   <filter-name>Remote Address Filter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>
...

Remove the corresponding Valve specification from ./cfusion/runtime/conf/server.xml. Bounce the server and verify that the custom error pages are still being served appropriately.

In my next post, we’ll figure out what’s going on with IPv6-based URI’s and why we’re still being blocked (although now we at least get our custom error page). And as noted above, we’ll revisit this whole subject of address-based access restrictions at least one more time in the future.

Tomcat: Custom Error Pages

This is the latest in my series of short posts related to configuring Tomcat, as I work on getting a Tomcat/ACF10 development environment stood up next to my existing Apache/JRun/ACF9 application stack. See the first post in the series for a bit of background.

There are several reasons you may want to set up custom error pages to be served by Tomcat when different kinds of errors or exceptions are encountered. These reasons might include:

  • Security: the default error pages served by Tomcat can include information about the server and its configuration that could be considered a vulnerability (e.g.., file paths, configuration or version information)
  • Application-specific error handling: you may want to provide site- or application-specific information about the error to assist the user (or the developer!)

Part of the servlet specification allows for the definition of error pages to be served up based on either an exception or an error code in the following format:

<web-app>
   ...
   <error-page>
      <exception-type>java.lang.NullPointerException</error-code>
      <location>/nullpointer.jsp</location>
   </error-page>

   <error-page>
      <error-code>404</error-code>
      <location>/404.html</location>
   </error-page>
   ...
</web-app>

The specific files served up can be static HTML or dynamic pages of any type supported by the server. The paths are relative to the root of the web application.

Because the default error pages served up by Tomcat include version information, I typically define a basic set of error pages for HTTP 403 and 404 status codes, place those pages in a ./errors/ folder off the Web root and then reference them in ./WEB-INF/web.xml for my application.

Tomcat: Default Web Document List

This is the sixth in my series of short posts covering the different aspects of setting up a development environment based on Tomcat and Adobe’s ColdFusion 10 application server stack. For background on this, see the initial post in the series.

The list of default documents the server will provide is specified in ./cfusion/runtime/conf/web.xml and then replaced (if specified) in the ./WEB-INF/web.xml file within each defined context. As all of the ColdFusion configuration is handled at the context level, it makes sense to make this particular change also at the context level. Find the welcome-file-list element toward the end of file ./cfusion/wwwroot/WEB-INF/web.xml and add the needed entries:

<welcome-file-list ...>
   <welcome-file>index.shtm</welcome-file>
   <welcome-file>index.cfm</welcome-file>
   <welcome-file>index.html</welcome-file>
   <welcome-file>index.htm</welcome-file>
   ...
</welcome-file-list>

Note that order does matter here: the first file found from the list will be served up when the request does not specify the file name. As shown above, we’ll look for index.shtm (which necessitates enabling SSI to function), then index.cfm, then static HTML pages index.html and index.htm. This sequence is specific to how our applications are configured; adjust accordingly per your own configuration needs.

Make the needed changes and restart the server.

Tomcat: Enabling SSI

This is the fifth in my series detailing my efforts to stand up a Tomcat/ACF10 development environment next to my existing Apache/JRun/ACF9 stack. For background, see the first post in the series.

Enabling Tomcat’s ability to process server-side includes (SSI) requires changes to two configuration files. File ./cfusion/runtime/conf/web.xml contains definitions for both a filter and a servlet for processing SSI’s, as well as a pair of corresponding servlet-mapping and filter-mapping definitions for filenames matching the *.shtml pattern. Uncomment either the filter or the servlet element (but not both), and the corresponding -mapping element. Modify the -mapping element based on the naming conventions you use and/or add additional -mapping elements, as needed.

If you decide to go the filter route on this, you should also note that the default web.xml file’s definition of the filter determines whether to run files through the SSI processing based on the MIME-type of the file. You will almost certainly have to also uncomment, and possibly supplement, the entry/entries in the MIME-type mappings in the same file.

The second file that requires a tweak, per the Tomcat SSI How-To, is ./cfusion/runtime/conf/server.xml. As noted in the docs, only contexts configured as “privileged” can use the SSI capabilities. Add the privileged="true" attribute to Context element for the ColdFusion context:

<Context
   path="/"
   docBase="/Applications/ColdFusion10/cfusion/wwwroot"
   ...
   privileged="true"
>
...
</Context>

Throw together a quick test SSI file, bounce your server, and verify that it works.

I clearly have some additional homework to do on this one, as I dont yet understand the benefits and drawbacks of the filter-vs-servlet choice above. More to come on that.