Site Network: Personal | Professional | Photography

Technical Blog

This blog will contain content related to Java, Seam, Security, my sites and projects, as well as other technical subjects I am interested in.

Comments and questions are welcome!

Getting the Real IP Address from a Proxied Request in ATG

Tuesday, April 8th, 2008

Many things can obscure the real IP address of the end user when they visit your site: a load balancer in front of your ATG cluster, Akamai, the user's ISP or office network, and more. This makes correlating logging events, or using the ATG session IP validation security option, and more, very difficult. In light of that challange I've added a new mini-module to my Open Source ATG Modules called the ProxyIPFixer. It uses a simple ATG pipeline Servlet to examine the X-FORWARDED-FOR request header, and if it finds one, parse through the IP addresses to find the originating IP address of the user, and puts that value into the ATG Request object's remoteAddr property.

This allows downstream pipeline servlets, code, and pages to see the real user's IP address.

The caveat is that the header can be faked, and that some ISPs/companies, such as AOL, do not set the true end point of the user, and you can only see back to their outgoing proxy server. In AOL's case in particular, they can also route subsequent requests by the same AOL user through different AOL proxy points, which will make it appear that someone is hijacking a session (if you're using the ATG session security mechanism). So be aware of the limitations. However it can be very useful.

For those who don't want to download the whole module package, I have attached the Java source and the ATG properties file to this post.

Enjoy! (and as always feel free to contact me with questions, issues, improvements, etc...)

ProxyIPFixerServlet Java Source

ProxyIPFixer ATG Properties File

login-required=”true” Will End Your Conversation

Monday, March 10th, 2008

In Seam, in the pages.xml or mypage.page.xml files, you note that a given page requires the user to be logged in to view the page. It is a very easy way of handling simple security. What happens is if a user attempts to access a page with the login-required="true" attribute and they are not logged in, they are automatically redirected to your login page (as defined in your pages.xml). Once they login, they are automatically redirected back to the page they had attempted to access initially. Very elegant, and much easier than writing all that yourself.

There is however a "gotcha" you should be aware of in this flow. If you use the login page, or logic, to start a long running conversation (I do this because my User entity object has some large binary properties which I want lazily loaded), the post-login redirection will kill that conversation. In my case this led to lazy loading exceptions down the road.

It took me a while to figure out the cause, as it only happened much later in the application, and most of the time it worked (when I logged in purposefully from the main page), but sometimes would break (when I'd had an expired session and gone through the login auto-redirection flow). Eventually though I was able to track it down to those two scenarios.

What is happening is this: before the first redirection happens (to the login page), the Seam Redirect classes captureCurrentView method is called. This basically saves the information about the page you were trying to view (it's a little more complex than that- being all Faces like and whatnot, but that's the gist of it). This method creates a long running conversation in order to hold this state across the multiple pages. If there was no previous long running conversation to join, and it had to create a new conversation, it stores a conversationBegun flag of true.

Then you hit the login page, where the page (or code) would Begin a long running conversation, except you almost certainly have join=true, so it joins the existing long running conversation, which was created by the captureCurrentView method. This is the conversation your User entity was loaded up in.

After your login was successful, the Redirect classes returnToCapturedView method is called to send you back to where you'd tried to go initially.

This method has the following block:

 
if (conversationBegun) {
       Conversation.instance().end();
}
 

This ends the conversation you had loaded your User entity within, and when you hit your destination page, there is no long running conversation at all. Then, a few minutes later, it's lazy loading exception time.

The downside is there isn't a really clean fix that I am aware of yet.

The upside is there is a pretty simple hack: just add a <begin-conversation join="true" /> to all of your pages which have the login-required="true" attribute. This creates a new long running conversation before the Redirect does it's work, so it in turn joins that conversation instead of creating a new one, the conversationBegun flag is false, and the returnToCapturedView method doesn't end your conversation. It's a hack, and you have to remember to add it to every page which requires a logged in state, but it does work.

Don’t like people leeching your wireless?

Friday, November 30th, 2007

Don't just block them, get a little more creative....

http://www.ex-parrot.com/~pete/upside-down-ternet.html

Enjoy:)

CAPTCHA with Seam in Three Minutes

Sunday, October 21st, 2007

Adding a CAPTCHA to a form using Seam is easy now that Seam is bundling jCaptcha.

The Seam documentaiton is good, and can be found in section 13.9 here:

http://docs.jboss.com/seam/2.0.0.CR2/reference/en/html/security.html#d0e7755

If you used seam-gen to create your project, you will need to make a few changes.

First, you need to modify your project's ant build script to deploy the captcha jar into your ear (or possibly .war). In the target "ear" of the build.xml file, you will find a list of many jar files being copied from your project's lib directory into the ear. Simply add the captcha jar to that list, like this:

<include name="lib/jcaptcha-all-1.0-RC6.jar"></include>

Now that the jar is deploying, you need to reference it in the application.xml file found under your project's resources/META-INF directory. Add this entry:

<module>
<ejb>lib/jcaptcha-all-1.0-RC6.jar</ejb>
</module>

If you used seam-gen you will find that the Seam Resource Servlet is already defined in your web.xml so the step defined in the documentation in section 13.9.1 is not necessary.

(more...)

How to block an IP in Linux

Sunday, September 16th, 2007

I run Debian on my server, and I often find that my server is being attacked by other computers. Brute force SSH attacks, viruses scanning for the ability to spread, things like that. I'll go into the SSH brute force defenses in a later post, but for now I'll cover how to easily block an IP address.

First, I'll assume you are already using iptables. If you need help setting that up, use Google, Debian comes with it out of the box.

I have a small script called "block" which looks like this:
#!/bin/bash
sudo iptables -I INPUT -s $1 -j DROP
sudo bash -c "iptables-save &gt; /etc/network/iptables.save"

Whenever I find a "bad" IP in my logs or notifications, I just run:

block bad.ip.add.18

Substituting the bad ip for that nonesense above. This adds it to the list of IP address which iptables will simply drop any incoming packets from, and saves the in memory iptables configuration, so that it is preserved through reboots.

Then in your /etc/network/interfaces file, just add this at the bottom:

post-up iptables-restore /etc/network/iptables.save