Forum Discussion
mart_58302
Nimbostratus
Aug 15, 2008Serving wpad.dat with F5?
Hello.
Maybe wrong area, but I'm trying to find out, is it possible to use F5 himself as web server, to serve text based file like wpad.dat or cache.pac for clients?
How to do it?
23 Replies
- James_Quinby_46Historic F5 AccountMart -
It is possible to do this. Take a look at:
http://devcentral.f5.com/wiki/default.aspx/iRules/LTMMaintenancePage.html
...for an example. This particular iRule serves content directly from the LTM (in this case, a maintenance page) and shows how/where to put the text and uuencoded graphics. - mart_58302
Nimbostratus
It is possible to do this. Take a look at:
http://devcentral.f5.com/wiki/default.aspx/iRules/LTMMaintenancePage.html
...for an example. This particular iRule serves content directly from the LTM (in this case, a maintenance page) and shows how/where to put the text and uuencoded graphics.
Hmm, but can I do it with just iRule, as this http in one line and non easy editable is too complicated, actually the wpad.dat file is very simple javascript code like this:function FindProxyForURL(url, host) { if(shExpMatch(host, "*[^0123456789.]*") == false) if( isInNet(host, "127.0.0.0", "255.0.0.0") || isInNet(host, "172.17.0.0", "255.255.0.0") || isInNet(host, "172.18.0.0", "255.255.0.0") ) return "DIRECT"; else return "PROXY proxygateway.internal:8080; DIRECT"; )
I found one one similar example - http://devcentral.f5.com/Wiki/default.aspx/iRules/LTMMaintenancePageLite.html but didn't figure how how to access access it from F5 with url like this - http://wpad.internal/wpad.dat - hoolio
Cirrostratus
Hi Mart,
You can "serve" a page from LTM using HTTP::respond 200 content $http_content:when HTTP_REQUEST { Check if request is for wpad.internal/wpad.dat if {[string tolower "[HTTP::host][HTTP::uri]"] eq "wpad.internal/wpad.dat"}{ HTTP::respond 200 content {\ function FindProxyForURL(url, host) {\ if(shExpMatch(host, "*[^0123456789.]*") == false) \ if( isInNet\(host, "127.0.0.0", "255.0.0.0") \ || isInNet(host, "172.17.0.0", "255.255.0.0") \ || isInNet(host, "172.18.0.0", "255.255.0.0") \ ) \ return "DIRECT"; \ else \ return "PROXY proxygateway.internal:8080; DIRECT"; } } } }
Just escape the new lines in the payload with \. After you add the iRule, test it to make sure the content is as you expect and then run 'b load' to verify the LTM parser handles the meta-characters in the iRule correctly. Running 'b load' will reload the configuration so it shouldn't be done on a live box during production.
Aaron - mart_58302
Nimbostratus
You can "serve" a page from LTM using HTTP::respond 200 content $http_content:when HTTP_REQUEST { Check if request is for wpad.internal/wpad.dat if {[string tolower "[HTTP::host][HTTP::uri]"] eq "wpad.internal/wpad.dat"}{ HTTP::respond 200 content {\ function FindProxyForURL(url, host) {\ if(shExpMatch(host, "*[^0123456789.]*") == false) \ if( isInNet\(host, "127.0.0.0", "255.0.0.0") \ || isInNet(host, "172.17.0.0", "255.255.0.0") \ || isInNet(host, "172.18.0.0", "255.255.0.0") \ ) \ return "DIRECT"; \ else \ return "PROXY proxygateway.internal:8080; DIRECT"; } } } }
Just escape the new lines in the payload with \. After you add the iRule, test it to make sure the content is as you expect and then run 'b load' to verify the LTM parser handles the meta-characters in the iRule correctly. Running 'b load' will reload the configuration so it shouldn't be done on a live box during production.
Aaron
Great news. Just to be sure - so I must do new virtual server with this iRule only, without pool or nodes, as F5 is my only pool and node and iRule catches all traffic sent to wpad.dat and serve this file?
And I put this VIP address into DNS and F5 will serve it easily? But how van I do alias, as due historical reason I have few aliases, like cache1.pac, cache2.pac, which all right point to the wpad.dat file being symlinks in one Linux apache server, which serves right now this wpad.dat. - hoolio
Cirrostratus
If you attach that rule to a VIP with no default pool, the rule will answer requests made to the VIP with a host header value of wpad.internal with a URI of wpad.dat. If a request is made with a different host header value or a different URI, the request will be dropped because the rule will do nothing and there is no default pool to handle the request.
What type of aliases are you referring to? Do you want the VIP and rule to answer for more than just the /wpad.dat URI? If so, you can add more URI's using a switch statement:when HTTP_REQUEST { Check if requested Host header is wpad.internal if {[string tolower [HTTP::host]] eq "wpad.internal"}{ Check the requested URI switch -glob [HTTP::uri] { "/wpad.dat*" - "*cache1.pac" - "*cache2.pac" { HTTP::respond 200 content {\ function FindProxyForURL(url, host) {\ if(shExpMatch(host, "*[^0123456789.]*") == false) \ if( isInNet\(host, "127.0.0.0", "255.0.0.0") \ || isInNet(host, "172.17.0.0", "255.255.0.0") \ || isInNet(host, "172.18.0.0", "255.255.0.0") \ ) \ return "DIRECT"; \ else \ return "PROXY proxygateway.internal:8080; DIRECT";} } default { Take some default action? } } } }
Or you could answer all requests to the VIP with the wpad.dat file content:when HTTP_REQUEST { Send the wpad.dat content HTTP::respond 200 content {\ function FindProxyForURL(url, host) {\ if(shExpMatch(host, "*[^0123456789.]*") == false) \ if( isInNet\(host, "127.0.0.0", "255.0.0.0") \ || isInNet(host, "172.17.0.0", "255.255.0.0") \ || isInNet(host, "172.18.0.0", "255.255.0.0") \ ) \ return "DIRECT"; \ else \ return "PROXY proxygateway.internal:8080; DIRECT";} } }
Aaron - mart_58302
Nimbostratus
Or you could answer all requests to the VIP with the wpad.dat file content:
You are genius!
The global rule seems best, as I don't need to serve anything more on that VIP, but wpad.dat, so even aliases are not needed, so I inserted the iRule, activated it to VIP, without pools:when HTTP_REQUEST { Send the wpad.dat content HTTP::respond 200 content {\ function FindProxyForURL(url, host) {\ if(shExpMatch(host, "*[^0123456789.]*") == false) \ if( isInNet(host, "127.0.0.0", "255.0.0.0") \ || isInNet(host, "172.17.0.0", "255.255.0.0") \ || isInNet(host, "172.18.0.0", "255.255.0.0") \ ) \ return "DIRECT"; \ else \ return "PROXY proxy.polsise:8080; DIRECT"; \ else \ if( isPlainHostName(host) \ || shExpMatch(host, "*.internal") \ || shExpMatch(host, "*.testing") \ ) \ return "DIRECT"; \ else \ return "PROXY proxygateway.internal:8080; DIRECT";} } }
I can retrieve the code from wpad VIP, however, it doesn't work for browser, looking the result with browser I did found the newline mark in code - isPlainHostName(host) \ so is something in code missing? - hoolio
Cirrostratus
Sorry... the outside braces mean you don't need to escape the new lines.when HTTP_REQUEST { HTTP::respond 200 content { function FindProxyForURL(url, host) { if(shExpMatch(host, "*[^0123456789.]*") == false) if( isInNet\(host, "127.0.0.0", "255.0.0.0") || isInNet(host, "172.17.0.0", "255.255.0.0") || isInNet(host, "172.18.0.0", "255.255.0.0") ) return "DIRECT"; else return "PROXY proxygateway.internal:8080; DIRECT"; } } }
Aaron - mart_58302
Nimbostratus
Sorry... the outside braces mean you don't need to escape the new lines.
Yes! This is working! Big thanks and have nice weekend! - mart_58302
Nimbostratus
If you attach that rule to a VIP with no default pool, the rule will answer requests made to the VIP with a host header value of wpad.internal with a URI of wpad.dat. If a request is made with a different host header value or a different URI, the request will be dropped because the rule will do nothing and there is no default pool to handle the request.
What type of aliases are you referring to? Do you want the VIP and rule to answer for more than just the /wpad.dat URI? If so, you can add more URI's using a switch statement:when HTTP_REQUEST { Check if requested Host header is wpad.internal if {[string tolower [HTTP::host]] eq "wpad.internal"}{ Check the requested URI switch -glob [HTTP::uri] { "/wpad.dat*" - "*cache1.pac" - "*cache2.pac" { HTTP::respond 200 content { function FindProxyForURL(url, host) { if(shExpMatch(host, "*[^0123456789.]*") == false) if( isInNet\(host, "127.0.0.0", "255.0.0.0") || isInNet(host, "172.17.0.0", "255.255.0.0") || isInNet(host, "172.18.0.0", "255.255.0.0") ) return "DIRECT"; \ else return "PROXY proxygateway.internal:8080; DIRECT";} } default { Take some default action? } } } }
One small question, as I still must use (to be sure, that all users are using correct and full path) this iRule with alias, how to add also host alias like cache.internal etc into this iRule? - hoolio
Cirrostratus
Hi Mart,
So do you want to only send the HTTP content for requests with specific Host header values and/or URIs? If you have a list of hosts and/or URIs, you can either use a datagroup and matchclass command (Click here) or a switch statement (Click here) to check the request. The example you quoted uses a switch statement to check the URI.
Give one of those options a try and reply if you get stuck.
Aaron
Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects
