Separating HTTP from non-HTTP content on port 80
in aFleX
Posted by tcp-me
Can an aFlex switch HTTP content to my cache servers and non-HTTP content over the same port directly out to my firewall? My cache servers throw up a lot of error messages when non-HTTP content (such as P2P or Video) runes through it. Since it can't cache it, it would be great if the AX can switch it for me.
Thanks...
Can an aFlex switch HTTP content to my cache servers and non-HTTP content over the same port directly out to my firewall? My cache servers throw up a lot of error messages when non-HTTP content (such as P2P or Video) runes through it. Since it can't cache it, it would be great if the AX can switch it for me.
Thanks...
0
Comments
Hi,
As you know we have different VIP types on AX.
Type TCP: Accept any TCP traffic (doesn't look at Layer7)
Type HTTP: Accept HTTP traffic only (drop non web traffic)
Type UDP, SMTP, SSL-Proxy, etc: I won't talk about these one since they are not relevant to your case.
You can't use the VIP type HTTP since all non HTTP traffic will be dropped.
You have to use the VIP type TCP. And to reply to your need, you can use an aFlex that will check if the traffic is really web and if not, configure this aFleX to redirect the traffic to another Service Group ("sg_dgw" in my example) that has 1 real server = your_firewall:80.
Code:
when RULE_INIT { # Create a list of HTTP methods forwarded to CF # RFC 2616 set ::list_HTTP_Method [list "OPTIONS" "GET" "HEAD" "POST" "PUT" "DELETE" "TRACE" "CONNECT"] # RFC 2518 lappend ::list_HTTP_Method "PROPFIND" "PROPPATCH" "MKCOL" "COPY" "MOVE" "LOCK" "UNLOCK" # RFC 3253 lappend ::list_HTTP_Method "VERSION-CONTROL" "REPORT" "CHECKOUT" "CHECKIN" "UNCHECKOUT" "MKWORKSPACE" "UPDATE" "LABEL" "MERGE" "BASELINE-CONTROL" "MKACTIVITY" # RFC 3648 lappend ::list_HTTP_Method "ORDERPATCH" # RFC 3744 lappend ::list_HTTP_Method "ACL" # draft dusseault-htt-patch lappend ::list_HTTP_Method "PATCH" # draft reschke-webdav-search lappend ::list_HTTP_Method "SEARCH" } when CLIENT_ACCEPTED { # collect Client's first packet request TCP::collect 10 } when CLIENT_DATA { # Check if the client first packet is an HTTP request set URL_start [ expr [string first "/" [TCP::payload]] - 2] set method [string range [TCP::payload] 0 $URL_start] if { [lsearch $::list_HTTP_Method $method] != -1 } { set client_http true } else { set client_http false } } ################################## # If traffic not HTTP send to Internet ################################## if {!$client_http} { # log "Client traffic is not HTTP => Send to Internet" # you have defined a Service Group "sg_dgw" with 1 server in it = your default gateway pool $sg_dgw } else { ################################## # If traffic is HTTP ... ################################## } # Do nothing in the aFleX. Use the pool defined in the VIP }
Note: FYI in the future we'll provide you the ability within a VIP type HTTP to NOT drop non http traffic but send it to a specific Service Group. So you'll be able to use that option instead of the aFlex on VIP type TCP described above.
Keep us updated.
Dimitri
Thank you very much for putting that together. Tt looks like a very well thought out script. I'll try it out next week when I'm at the colo and have access to the staging pods.
-Jean
Here is what I did; not only try to separate HTTP, but also look into HTTP packet,
if Accept-Language is not included (all bower should have this, if not, maybe some P2P or software upgrade service) will also forward.
Also, I will try to collect the host and uri for log purpose since HTTP:host and HTTP:uri no longer could be used here.
One thing need to consider, this will only works for port 80 traffic which client sends packets first after handshake, if server sends back packet first, there might be some issues.
when RULE_INIT {
set ::enableNonHTTP 1
}
when CLIENT_ACCEPTED {
if { $::enableNonHTTP } {
TCP::collect
}
}
when CLIENT_DATA {
# If no "HTTP" contains in TCP payload, consider request non-http and
# sends to default gw
if { $::enableNonHTTP } {
if { [string first HTTP [TCP::payload]] < 0 } {
pool gw
} else {
# If HTTP and also contains "Access-Language" header, consider normal Web browsing
# use LLB links
if { [TCP::payload] contains "Accept-Language" } {
#
# Find out HTTP:Host and HTTP:URI for logging purpose
#
set host [ findstr [TCP::payload] "Host:" 6 "\r" ]
set uri [ getfield [TCP::payload] " " 2]
set remote_addr [IP::local_addr]
pool llb-links
} else {
# HTTP traffic generated by P2P or other C/S service, not normal HTTP browser and
# redirect to default gw as well
pool gw
}
}
TCP::release
}
}
#Below are used to send log only when server responded (valid HTTP response)
when SERVER_CONNECTED {
set nat_pro "TCP"
set nat_c_port [TCP::client_port]
set nat_c_nat_port [TCP::local_port]
set nat_d_port [TCP::server_port]
set curtime [TIME::clock seconds]
set ftime [clock format $curtime -format {%Y-%m-%d %H:%M:%S} ]
# Fomat NAT begin string
set log_str "$ftime NAT Created $nat_pro SRC [IP::client_addr]:$nat_c_port NAT [IP::local_addr]:$nat_c_nat_port DST [IP::server_addr]:$nat_d_port URL http://$host$uri"
# write to syslog
log local1. $log_str
}