Wednesday, September 10, 2014

Alteon AppShape++ Redirects

Lab goals

In the lab we will practice:

  • Redirection - r.dans-net.com should be redirected to 3.dans-net.com
  • Decision by URL matching:
    • If URL length is 1 or 2, not including the leading "/", then redirect to 3.dans-net.com
    • If URL is "/images/number.jpg" or "/icons/number.jpg" then select SRV1
    • URL begins with  "/alpha" or with "/beta" then select SRV2
    • URL contains "cgi-bin" or "gamma" then select SRV3
Both r.dans-net.com and 3.dans-net.com should resolve to 10.136.6.11.

Setup

I'll use my Loadbalancer Lab Setup.


The loadbalancer is Radware's Alteon VA version 29.5.1.0

Here is the /etc/hosts or c:\windows\system32\drivers\etc\hosts resolve snippet:


1
2
10.136.6.11     3.dans-net.com
10.136.6.11     r.dans-net.com

Alteon configuration

Fist lets create 3 groups, one for each SRV:



1
2
3
4
5
6
7
8
9
/c/slb/group g1
        ipver v4
        add 1
/c/slb/group g2
        ipver v4
        add 2
/c/slb/group g3
        ipver v4
        add 3

Next, lets configure create the VIP/virt:


1
2
3
4
 /c/slb/virt 6_11
        ena
        vip 10.136.6.11
 /c/slb/virt 6_11/service 80 http

Next the AppShape++ script. This time I'll show two parts. The draft and the final.

Draft Script

The draft script is a regular TCL script, where I test the script with regular TCL enviourment, such as ActiveTCL for windows.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#attach group g1
#attach group g2
#attach group g3
#
#when HTTP_REQUEST {
#}
#
#-----END

# usage
# redirect_url_match [URL] [HOST]

# set default values
set host "3.dans-net.com"
set url "/a"

# set values if exists
if {$argc == 1} {
    set url [lindex $argv 0]
} elseif {$argc > 1} {
    set host [lindex $argv 1]
}


# the code to use later on the alteon
if {[string equal $host "r.dans-net.com"]} {
    puts "redirect to 3.dans-net.com"
} else {
    # check length of url. since the cout also includes the leading / we need to add 1 to the comparison
    if {[string length $url] == 2 || [string length $url] == 3} {
        puts "redirect to 3.dans-net.com"
    # exact match    
    } elseif { [string match "/images/number.jpg" $url] || [string match "/icons/number.jpg" $url ] } {
        puts "SRV1"
    #match begin with    
    } elseif { [string match "/alpha*" $url] || [string match "/beta*" $url] } {
        puts "SRV2"
    # match contains X
    } elseif { [string match "*gama*" $url] || [string match "*cgi-bin*" $url] } {
        puts "SRV3"
    }

}


  • Lines 1-8 - This is my template for AppShape++ scripts. Its is currently commented out.
  • Lines 14-22 - Simulate HTTP headers and URL
    • We are basing our group/pool selection on Host name and URL, so we need to simulate those parameters.
    • Lines 14-15 - Set the default Host and URL
    • Lines 18-22 - Extract the URL and Host name from command line arguments.
    • The script can be run:
      • Without arguments: tclsh.exe my_script.tcl . Then the URL is "/a" and the host is "3.dans-net.com"
      • With just one argument: tclsh.exe my_script /gamma/a3.html. Then the URL is "/gamma/a3.html" and the host is "3.dans-net.com".
      • With two arguments: tclsh.exe my_script /gamma/a3.html r.dans-net.com. Then the URL is "/gamma/a3.html" and the host is "r.dans-net.com"
  • Lines 26-28 - Check if host name is "r.dans-net.com". If so, print "redirect to 3.dans-net.com". This is instead of actually using the Alteon command HTTP::redirect 
  • Lines 28-43 - Check the URL
    • Line 30 is checking the length of the URL.
    • Line 33 is checking exact match.for the URL
    • Line 36 is checking if the URL begins with....
    • Line 39 is checking if the URL contains ....
After running the script and checking that its actually working as indicated in the Lab Goals, we need to convert it to Alteon AppShape script:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
attach group g1
attach group g2
attach group g3
attach group 10

when HTTP_REQUEST {
    # exctract the fields from the HTTP headers
    set host [HTTP::host]
    set url [HTTP::uri]


    if {[string equal $host "r.dans-net.com"]} {
        HTTP::redirect "http://3.dans-net.com" 301
    } else {
        # check length of url. since the cout also includes the leading / we need to add 1 to the comparison
        if {[string length $url] == 2 || [string length $url] == 3} {
            HTTP::redirect "http://3.dans-net.com" 
        # exact match    
        } elseif { [string match "/images/number.jpg" $url] || [string match "/icons/number.jpg" $url ] } {
            group select g1
        #match begin with    
        } elseif { [string match "/alpha*" $url] || [string match "/beta*" $url] } {
            group select g2
        # match contains X
        } elseif { [string match "*gamma*" $url] || [string match "*cgi-bin*" $url] } {
            group select g3
        } else {
            group select 10
        }

    }
}

-----END

This is basically the same script as before, with just Alten AppShape++ commands like HTTP::redirect:  and group select

Notice that at line 28, we have a default action, which is to use group 10, which includes all web servers. This will allow serving the main page, javascript and css.

Also notice the difference between the redirect at line 13 and the redirect at line 17. The first will return 301 - permanent move, and the second will send the default 302 which is temporary move.

Now lets import the script and apply it to the virt configuration



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 /c/slb/appshape/script redirect_match_url
        ena
        import text 
 attach group g1
 attach group g2
 attach group g3
 attach group 10
 when HTTP_REQUEST {
     # exctract the fields from the HTTP headers
     set host [HTTP::host]
     set url [HTTP::uri]
     if {[string equal $host "r.dans-net.com"]} {
         HTTP::redirect "http://3.dans-net.com" 301
     } else {
         # check length of url. since the cout also includes the leading / we need to add 1 to the comparison
         if {[string length $url] == 2 || [string length $url] == 3} {
             HTTP::redirect "http://3.dans-net.com" 
         # exact match    
         } elseif { [string match "/images/number.jpg" $url] || [string match "/icons/number.jpg" $url ] } {
             group select g1
         #match begin with    
         } elseif { [string match "/alpha*" $url] || [string match "/beta*" $url] } {
             group select g2
         # match contains X
         } elseif { [string match "*gamma*" $url] || [string match "*cgi-bin*" $url] } {
             group select g3
         } else {
             group select 10
         }
     }
 }
 -----END
 

 /c/slb/virt 6_11/service 80 http
        dbind forceproxy
 /c/slb/virt 6_11/service 80 http/appshape
        add 10 redirect_match_url

Test

First I tried some redirection tests. The best way to see them is using chrome or firefox developer tools and have a look at the network tab. However, this is not the best way to show it here as the data is hierarchical and I can't show in one snapshot how redirection worked.

So I used wireshark to show the redirection.



  • Packet 4 is the request for r.dans-net.com
  • Packet 6 is the reply with the redirect
  • Packet 7 is the new request to the redirected host
Next lets see how the page looks like:


We can see that reach element (in red) is using the correct SRV.

Summary

I really like TCL. It is very simple. So is AppShape++.