Showing posts with label loadbalancer. Show all posts
Showing posts with label loadbalancer. Show all posts

Friday, February 20, 2015

Alteon AppShape++ persistency and multiple scripts per service

Lab goal

Create new VIP on 10.136.6.17.

Using an AppShape++ script to choose the preconfigured group/pool "10".

Once the laodbalancer chooses a server, all requests from the client's source IP should go to the same server. This is called persistence or stickiness.

Setup

I'll use my Loadbalancer Lab Setup.

The loadbalancer is Radware's Alteon VA version 29.5.1.0

The initial Alteon VA configuration can be found here.

Notice the group and hosts are preconfigured:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/c/slb/real 1
        ena
        ipver v4
        rip 10.136.85.1
/c/slb/real 2
        ena
        ipver v4
        rip 10.136.85.2
/c/slb/real 3
        ena
        ipver v4
        rip 10.136.85.3
/c/slb/group 10
        ipver v4
        add 1
        add 2
        add 3

 

Alteon configuration

First the AppShape++ script:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
/cfg/slb/appshape/script take_10/en/import


attach group 10

when HTTP_REQUEST {
    group select 10
}

-----END

Line 1 - This allows to just copy paste the whole text to Alteon's CLI. It defines a script if its not exists, enable it and imports it.
Line 7 - Selects group 10.

Next, lets configure VIP/virt with its services:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
/c/slb/virt 6_17
       ena
       ipver v4
       vip 10.136.6.17
/c/slb/virt 6_17/service 80 http
       group 1
       rport 80
       pbind clientip norport
       dbind forceproxy
/c/slb/virt /service 80 http/appshape
       add 10 take_10

Line 8 - Add the stickiness/persistence part, based on the clients IP address.
Line 11- Add AppShape++ script.

 

Test


This didn't go well. We still see that all servers were used and not just one.

The reason for that is that once we select a group/pool using AppShape++, Alteon will ignore pbind settings.

 

Another try

AppShape++ has the following command : persist

This command can be used to create a persistence/stickiness .

One way we can use this command is by fixing our script. Another way would be to create another script and add it to the service. Using a separate script will allow us to reuse that script on more than on service / VIP.


1
2
3
4
5
6
7
/cfg/slb/appshape/script persist/en/import

when HTTP_REQUEST {
    persist source_addr 255.255.255.255
}

-----END

Line 4 - Create persistence/stickiness by using the source IP address with /32 mask.

Now lets add it to the service:

1
2
/c/slb/virt 6_17/service 80 http/appshape
       add 16 persist

Line 2 - We have added the new AppShape++ script to the service. We use priority 16  which means this will run after priority 10 which was take_10 script.

 

Another Test 

It works! SRV3 was selected for all HTTP requests.

We can also have a look at the persistance table:


1
2
3
4
5
>> LB1 - Persistency Information# /i/slb/persist/dump 

 Printing Data Table Entries for SP 1
key-10.136.3.1,vs:10.136.6.17,80,g:10,value-g:10 rs:3 80, age 178
Total number of session IDs: 1

Line 1 - Is the command to show all persistence object, in yellow.
Line 4 - Me in red, is using SRV3 in green, and the idle timeout is 178 seconds in blue.

 

Summary

So we learned that not everything we configure on the VIP/virl service applies when we use AppShape++.

We also learned how and why to use more than one script per service.

Enjoy...

Friday, December 5, 2014

Alteon's REST API

AlteonOS has a reach REST API for monitor, operation, and configuration.

REST can be used/called with verity of programming languages, or even just using wget. However, since this blog was already using TCL for AppShape++ scripting, we may as well keep using TCL for REST too. However, RESTing with TCL is a bit pain in the ..., so this time I'll use python instead.

All most forgot to explain what REST is. Its a way to run remote procedures calls using HTTP. Example calls:
  1. Read interface counters
  2. Update real's weight
  3. Bring down a real inside a group
I strongly recommend using  a browser plugin for testing out REST calls. I use HttpRequest for firefox.

Here are two screenshots. The first is how I get the current status of real 1, and the second is how I disable real 1.



 

 

 Lab goal


Using the base setup, create python script to toggle the status of real 1 from not enabled to enabled and from disable to enable.

 

Setup


I'll use my Loadbalancer Lab Setup.

The loadbalancer is Radware's Alteon VA version 29.5.1.0

The initial Alteon VA configuration can be found here.

Notice the group and hosts are preconfigured:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/c/slb/real 1
        ena
        ipver v4
        rip 10.136.85.1
/c/slb/real 2
        ena
        ipver v4
        rip 10.136.85.2
/c/slb/real 3
        ena
        ipver v4
        rip 10.136.85.3
/c/slb/group 10
        ipver v4
        add 1
        add 2
        add 3

 

Python script


I have used python 2.7 and the following modules: json and requests

Alteon's REST API is using json as its data format. Python's build in json module converts python dict to json format and vice-versa.

requests is a very easy python module to use for REST API.

Here is the source code for the python script. See the comments inside for explanations:


 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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import requests
import json
import sys


# set Alteon and real parameters
ALTEON = "10.136.1.100"
REAL = "1"
USER = "admin"
PASSWORD = "admin"

# get the current status of real server
# ============================================================

# set authentication object
myAuth=requests.auth.HTTPBasicAuth(USER, PASSWORD)

# set request string with the ALTEON name/ip address and the 'real' we want to toggle
reqSTR =  "https://"+ALTEON+"/config/SlbOperEnhRealServerTable/" + REAL

# turn off SSL warning. Don't do this in production!
# see here how to deal with it http://docs.python-requests.org/en/latest/user/advanced/#ssl-cert-verification

requests.packages.urllib3.disable_warnings()

# send the request, use the auth object, don't verify certification and return a python dct out of json string
# The return is a one item dict with  'SlbNewCfgEnhRealServerTable' as key. 
# That item contains one item list, hence the [0]
# That list item is another dict with two entries: 'Status' and 'Index' we need the Status
r = requests.get(reqSTR, auth=myAuth, verify=False).json()['SlbOperEnhRealServerTable'][0]
state = r['Status']


# print current state and set the new requierd state
if state == 1:
    print "Real is enabled. Changing status to disabled"
    newStatus = "2" # disabled
elif state == 2:
    print "Real is disabled. Changing status to enabled"
    newStatus = "1" # enabled
elif state == 3:
    print "Real is disabled but waiting for cookies to timeout. Changing status to enabled"
    newStatus = "1" # enabled
elif state == 4:
    print "Real is disabled but waiting for sessions to timeout. Changing status to enabled"
    newStatus = "1" # enabled
elif state == 5:
    print "Real is disabled but waiting for sessions to timeout and for cookeis to timeout. Changing status to enabled"
    newStatus = "1" # enabled
else:
    # we should never get here
    print "error retrieving real status. return object:"
    print r
    sys.exit(0)

# set the new real status
# ============================================================

# create JSON data to be passed
myData = json.dumps({'Status' : newStatus})

# send the oper command to change the status. Notice that his time the method is PUT
r = requests.put(reqSTR, auth=myAuth, verify=False, data=myData).json()['status']

# print the return status of the command
print r

Test



Notice how the status is changing from one run to the other.

 

Summary


Alteon's REST API is easy to use and straight forward. It is way better then using expect scripts for automation.

 


Thursday, November 6, 2014

Alteon - each server is different

Lab goal

Create VIP 10.136.6.16 with the following servers/reals:
  • "r8080" - 10.136.85.1 port 8080
  • "r8081" - 10.136.85.2 port 8081
  • "r8082" - 10.136.85.3 port 8082
The group name should be "gMulti".

Setup

I'll use my Loadbalancer Lab Setup.

The loadbalancer is Radware's Alteon VA version 29.5.1.0

The initial Alteon VA configuration can be found here.

Alteon configuration

First lets add the reals.



 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
/c/slb/real r8080
       ena
       ipver v4
       rip 10.136.85.1
       addport 8080
/c/slb/real r8081
       ena
       ipver v4
       rip 10.136.85.2
       addport 8081
/c/slb/real r8082
       ena
       ipver v4
       rip 10.136.85.3
       addport 8082
/c/slb/group gMulti
       ipver v4
       add r8080
       add r8081
       add r8082
/c/slb/virt 6_16
       ena
       ipver v4
       vip 10.136.6.16                   
/c/slb/virt 6_16/service 80 http
       group gMulti
       rport 0       

  • Lines 1-15 : Configure the real servers
    • Notice the addport command, which sets the port being used by the server.
  • Lines 16-20: Create a new group and adds the previously defined servers
  • Lines 21-27: Create the VIP
    • Notice line 27, which states that the Alteon should use the rport configured on a real server's configuration.

Test


Notice the SRV_PORT and SRV_ADDR, which shows that the 808X port is being used.

But a better way to see that is to see the sessions in the session table:



1
2
3
4
5
6
7
8
9
>> LB1 - Session Table Information# /i/slb/sess/cip 10.136.3.1 

 Printing Sessions for SP 1
1,01: 10.136.3.1 50040, 10.136.6.16 http -> 2094 10.136.85.3 8082 tcp age 10 v:1  E
1,01: 10.136.3.1 50041, 10.136.6.16 http -> 2095 10.136.85.2 8081 tcp age 10 v:1  E
1,01: 10.136.3.1 50042, 10.136.6.16 http -> 2096 10.136.85.1 8080 tcp age 10 v:1  E
1,01: 10.136.3.1 50043, 10.136.6.16 http -> 2097 10.136.85.3 8082 tcp age 10 v:1  E
1,01: 10.136.3.1 50044, 10.136.6.16 http -> 2098 10.136.85.2 8081 tcp age 10 v:1  E
1,01: 10.136.3.1 50046, 10.136.6.16 http -> 2100 10.136.85.3 8082 tcp age 10 v:1  E

Summary

As usual, the configurations are simple and straight forward.

Tuesday, November 4, 2014

Alteon SSL key import wows

I was trying to import a new certificate with an SSL key, but it was without success.

But as usual, before trying that on production, I tried that on my lab setup. It was done without any problems.

But when trying with the production Alteon, running the same 29.5.1 version, I got this message:

> -----END RSA PRIVATE KEY-----
Enter key passphrase:
Error: The private key is not a valid RSA key

Error: Failed to extract key XXXXX


After trying it several times, comparing some random strings inside the key I noticed a lag when I pasted the key to the production Alteon. The reason for the lag was SecureCRT that was configured to insert delays between keys. This feature is extremely useful with pasting large text into NX-OS.


My lab setup is with the default Line Send delay of 5ms and Character send delay of 0ms.

So I tried to use the lap SecureCRT delay setup on my production Alteon, and to my surprise it worked!

So to sum up: when pasting to Alteon 29.5.1, you better use the default SecureCRT delay settings.

One more thing and this will save you precious time digging through the command reference:

"key" and "srvrcert" names must be identical

Friday, September 26, 2014

Change HTTP reply content with AppShape++

Lab goal

When a clients asks for beta/a2.html, return "Hello" instead.

Use VIP 10.136.85.14

Setup

I'll use my Loadbalancer Lab Setup.


The loadbalancer is Radware's Alteon VA version 29.5.1.0

The initial Alteon VA configuration can be found here.

Notice the group and hosts are preconfigured:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/c/slb/real 1
        ena
        ipver v4
        rip 10.136.85.1
/c/slb/real 2
        ena
        ipver v4
        rip 10.136.85.2
/c/slb/real 3
        ena
        ipver v4
        rip 10.136.85.3
/c/slb/group 10
        ipver v4
        add 1
        add 2
        add 3

Alteon configuration

First, lets configure the VIP/virt.

Remember routing! The returning traffic needs to go through the Alteon, otherwise TCP will break. So we also need to configure Proxy IP/SNAT so return traffic will go through the Alteon.


1
2
3
4
5
6
7
8
 /c/slb/virt 85_14
        ena
        vip 10.136.85.14
 /c/slb/virt 85_14/service 80 http
        group 10
 /c/slb/virt 85_14/service 80 http/pip
        mode address
        addr v4 10.136.85.200

Next we need to write the Appshape++ script:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
when HTTP_REQUEST {
    # retrieve URL from the request
    set url [HTTP::uri]
    set reply {
        <html>
        <body>
        <h1>Hello!</h1>
        <body>
        </html>
    }

    # check if URL is with /beta/a2.html
    if {[string match "/beta/a2.html" $url] == 1} {
        # change the URL and select SRV1
        HTTP::respond 200 content $reply
    }
}

-----END


  • Line 1-17 - When a request comes in do:
    • Line 3 - Extract the URL
    • Line 4-10 - Set a response content.
    • Lines 13-16 - If the URL is "beta/a2.html" then:
      • Line 15 - Respond with code 200 and the content we set earlier.
  • Line 19 - The end of the script.
Now lets import the script and apply it to the VIP/virt:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 /c/slb/appshape/script respond
        ena
        import text 
 when HTTP_REQUEST {
     # retrieve URL from the request
     set url [HTTP::uri]
     set reply {
         <html>
         <body>
         <h1>Hello!</h1>
         <body>
         </html>
     }
     # check if URL is /beta/a2.html
     if {[string match "/beta/a2.html" $url] == 1} {
         # change the URL and select SRV1
         HTTP::respond 200 content $reply
     }
 }
 -----END
 
 /c/slb/virt 85_14/service 80 http/appshape
        add 10 respond

Test


Notice the "Hello!". Success!

Summary

After writing few AppShape++ , a pattern emerges: It really easy :)

Thursday, September 18, 2014

Using AppShape++ to change a request's URL

Lab goal

  • When a clients asks for /cgi-bin/* change that to /alpha/a1.html, and serve it from SRV1 
  • Fix the 404 page not found.

Use VIP 10.136.6.13.

Setup

I'll use my Loadbalancer Lab Setup.


The loadbalancer is Radware's Alteon VA version 29.5.1.0

The initial Alteon VA configuration can be found here.

Notice the group and hosts are preconfigured:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/c/slb/real 1
        ena
        ipver v4
        rip 10.136.85.1
/c/slb/real 2
        ena
        ipver v4
        rip 10.136.85.2
/c/slb/real 3
        ena
        ipver v4
        rip 10.136.85.3
/c/slb/group 10
        ipver v4
        add 1
        add 2
        add 3

Alteon configuration

Lets first create the VIP/virt and test it out.


1
2
3
4
5
 /c/slb/virt 6_13
        ena
        vip 10.136.6.13
 /c/slb/virt 6_13/service 80 http
        group 10

To fix the 404 at the bottom of the webpage, we need to change the request URL from /not_here to /here.html.

So lets write the AppShape++ script:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
attach group 10

when HTTP_REQUEST {
    # retrieve URL from the request
    set url [HTTP::uri]

    # check if URL begins with /cgi-bin/
    if {[string match "/cgi-bin/*" $url] == 1} {
        # change the URL and select SRV1
        HTTP::uri "/alpha/a1.html"
        group select 10 server 1
    # check if the request is for /not_here
    } elseif {[string match "/not_here" $url] == 1} {
        # change the URL to here.html
        HTTP::uri "/here.html"
    }
}

-----END


  • Line 1 - declare that we are about to use group 10.
  • Lines 3 - 17 - When HTTP_REQUEST comes from the client to the VIP do this:
    • Line 5 - Retrieve the URL
    • Lines 8-13 - Check if the URL begins with /cgi-bin/ if so:
      • Lines 10-11 - Send the request to the web server as "/alpha/a1.html" and select SRV1.
    • Lines 13-16 - Check if the URL is not_here if so:
      • Line 15 - Send the request to the web server as "here.html"
Now lets apply this script to the Alteon:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
 /c/slb/appshape/script set_url
        ena
        import text 
 attach group 10
 when HTTP_REQUEST {
     # retrieve URL from the request
     set url [HTTP::uri]
     # check if URL begins with /cgi-bin/
     if {[string match "/cgi-bin/*" $url] == 1} {
         # change the URL and select SRV1
         HTTP::uri "/alpha/a1.html"
         group select 10 server 1
     # check if the request is for /not_here
     } elseif {[string match "/not_here" $url] == 1} {
         # change the URL to here.html
         HTTP::uri "/here.html"
     }
 }
 -----END

 /c/slb/virt 6_13/service 80 http/appshape
        add 10 set_url


  • Lines 1-19 - importing the script
  • Lines 21-22 - applying the script to the VIP

Test


Before:



After:


Success!

Notice how the CGI script, which shows connection data (it just prints ENV vars), changed to show a static page from SRV1 and also notice that the 404 is fixed.

Summary

Setting the URL is really easy, once you know how.... :)

Friday, September 12, 2014

HTTP to HTTPs redirect with a twist

Lab goal

Create a new VIP/virt - 10.136.85.13.

The main page should be using HTTP but all the other elements should be using SSL.


Setup

I'll use my Loadbalancer Lab Setup.



The loadbalancer is Radware's Alteon VA version 29.5.1.0

The initial Alteon VA configuration can be found here.

Alteon configuration

We will reuse group 10 which includes all web servers.

So all is left is to create a VIP/virt with services HTTP and HTTPS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
 /c/slb/virt 86_13
        ena
        ipver v4
        vip 10.136.85.13
 /c/slb/virt 86_13/service 80 http
        group 10
        rport 80
 /c/slb/virt 86_13/service 80 http/pip
        mode address
        addr v4 10.136.85.200 
 /c/slb/virt 86_13/service 443 https
        group 10
        rport 443
 /c/slb/virt 86_13/service 443 https/pip
        mode address
        addr v4 10.136.85.200 

Lines 8-10 - Source NAT. Without it traffic from the server will go directly to client without going first through the Alteon.

Now for the AppShape script:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
when HTTP_REQUEST {
    # exctract the fields from the HTTP headers
    set url [HTTP::uri]
    set host [HTTP::host]


    if {[string equal $url "/"] ==0} {
        HTTP::redirect "https://$host$url" 301
    }
}

-----END


  • Line 7 checks if the path is not  /" and then:
    • Line 8 Redirect all requests to the page elements, such as pictures, iFrames and CGI-BIN to HTTPS
    • Notice that the redirect was built with the extracted host name and the URL
Next lets import and apply the AppShape++ script:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
 /c/slb/appshape/script redirect_to_https
        ena
        import text 
 when HTTP_REQUEST {
     # exctract the fields from the HTTP headers
     set url [HTTP::uri]
     set host [HTTP::host]
     if {[string equal $url "/"] ==0} {
         HTTP::redirect "https://$host$url" 301
     }
 }
 -----END

 /c/slb/virt 86_13/service 80 http/appshape
        add 10 redirect_to_https

Test


It looks like a regular HTTP page, but notice the TCP port being used inside the iFrame. Its 443, which is HTTPS.

Success!

Summary

This exact setup can be done with crule,but I think that using AppShape++ is much easier to understand, as you see the condition and the action in one place.

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++.

Monday, September 8, 2014

Select group/pool by query URI

Lab goal

When a request looks like this: http://a3.dans-net.com/group=GROUPNAME then the group/pool will be selected by the following name:

group_GROUPNAME

For example for http://10.136.5.10/group=g1 the selected group will be group_g1

The following groups should be defined:
  • g1 - SRV1
  • g2 - SRV2
  • g3 - SRV3

The VIP should be 10.136.5.10

Setup

I'll use my Loadbalancer Lab Setup.



The loadbalancer is Radware's Alteon VA version 29.5.1.0

The initial Alteon VA configuration can be found here.

Alteon configuration

First, lets configure the groups.

 /c/slb/group g1                          
        add 1
 /c/slb/group g2
        add 2
 /c/slb/group g3
        add 3

Next lets write the script.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
attach group g1
attach group g2
attach group g3

when HTTP_REQUEST {
    set group_exists [regexp -nocase {group=(g[0-9]+)(&.*)*$} [HTTP::query] a group_name]
    if {$group_exists == 1} {
        group select $group_name
    }
}

-----END



  • Lines 1-3 declare the groups which will be used later on.
  • Line 6 has the regular expression matching
    • The matching is case insensitive.
    • It looks for a group=g* in the query part of the URI.
    • If a match is found it will 
      • set group_exists to 1
      • put what ever matches in a
      • the result of the first parenthesis (g[0-9]+) to group_name
  • Line 7-8 - If a match  was found, select the group according to the group name
  • Line 12 - As allways we need the -----END to mark the end of script.

Next lets configure the virtual server. Notice that since we are using 10.136.5.X address as VIP, we need to configure the Alteon to use Source NAT/Proxy IP so return traffic from the servers go through Alteon and not directly back to the client.

 /c/slb/virt 5_10
        ena
        vip 10.136.5.10
 /c/slb/virt 5_10/service 80 http
        group 10
 /c/slb/virt 5_10/service 80 http/pip
        mode address
        addr v4 10.136.85.200 255.255.255.255 

Notice we added group 10 to the config. We need this as last resort group. If the AppShape++ script won't choose a group, that group will be chosen.

Next we need to import and apply the AppShape++ script to the HTTP service.

 /c/slb/appshape/script host_by_query
        ena
        import text 
 attach group g1
 attach group g2
 attach group g3
 when HTTP_REQUEST {
     set group_exists [regexp -nocase {group=(g[0-9]+)(&.*)*$} [HTTP::query] a group_name]
     if {$group_exists == 1} {
         log "$group_exists $a $group_name"
         group select $group_name
     }
 }
 -----END


 /c/slb/virt 5_10/service 80 http/appshape
        add 10 host_by_query

Test

First we will try selecting group g1:



Notice that just the GET to the main page was sent with ?group=g1&b=1 . The rest of the requests went without the query string.

Next g3:


Success!

Summary

That wasn't too hard, was it? The one thing I do is to test the TCL script on tclsh and only then import it to the Alteon. That is much faster then copy pasting into the Alteon's config.

Thursday, September 4, 2014

AppShape++ and SSL offloading

After running my fist AppShape++ script, I was wondering if it will work with SSL offloading as well.

Lets try it out, using my lab setup again, and I'll be adding on top my previous lab.



First I'll need to create SSL policy on the Alteon VA version 29.5.1.0:

 /c/slb/ssl/sslpol mySSL_Pol
        cipher "high"
        ena

This will select only high security encryption and integrity algorithms.

Next we need to create a self signed certificate:

>> LB1 - SSL Policy mySSL_Pol# /cfg/slb/ssl/certs/srvrcert

Enter server certificate id: mySRV_Cert
------------------------------------------------------------------
[Server certificate mySRV_Cert Menu]
     name     - Set descriptive certificate name
     generate - Create or update self-signed server certificate
     del      - Delete server certificate
     cur      - Display current server certificate configuration

>> LB1 - Server certificate mySRV_Cert# gen
This operation will generate a self-signed server certificate.
Enter key size [512|1024|2048|4096] [1024]: 2048
Enter server certificate hash algorithm [md5|sha1|sha256|sha384|sha512] [sha1]: sha256
Enter certificate Common Name (e.g. your site's name):  *.dans-net.com
Use certificate default values? [y/n]: y
Enter certificate validation period in days (1-3650) [365]: <enter>  
....
Self signed server certificate, certificate signing request and key added.

We also need to enable SSL globally:

/cfg/slb/ssl/on

Now lets add SSL offloading to virt 6_10:

 /c/slb/virt 6_10/service 443 https/ssl
        srvrcert cert mySRV_Cert
        sslpol mySSL_Pol
 /c/slb/virt 6_10/service 443 https/appshape
        add 10 group_by_host

Notice that not only SSL offloading was added, but also we applied the AppShape++ script.

Lets try it out:




Notice that the background is still blue, which means its HTTPS and that the SRV_PORT is 80, so we really have SSL offloading and the AppShape++ script works with SSL offloading too.


So yes! AppShape++ works also when using SSL offloading.