Citrix ADC

将 Apache mod_rewrite 规则迁移到默认语法

Apache HTTP 服务器提供了一个称为 mod_rewrite 的引擎,用于重写 HTTP 请求 URL。如果将 mod_rewrite 规则从 Apache 迁移到 Citrix ADC,则可以提高后端服务器性能。此外,由于 Citrix ADC 通常负载平衡多个(有时是数千个)Web 服务器,因此在将规则迁移到 Citrix ADC 之后,您将对这些规则拥有一个单一的控制点。

下面是 mod_rewrite 函数的示例,以及将这些函数转换为 Citrix ADC 上的重写和响应程序策略。

将 URL 变体转换为规范 URL

在某些 Web 服务器上,您可以拥有一个资源的多个 URL。虽然应使用和分发规范 URL,但其他 URL 可以作为快捷方式或内部 URL 存在。无论用于发出初始请求的 URL 如何,您都可以确保用户都能看到规范 URL。

在以下示例中,URL /~user 将转换为 /u/user。

用于转换 URL 的 Apache mod_rewrite 解决方案

RewriteRule ^/~([^/]+)/?(.*) /u/$1/$2[R]

用于转换 URL 的 Citrix ADC 解决方案

add responder action act1 redirect '"/u/"+HTTP.REQ.URL.AFTER_STR("/~")' -bypassSafetyCheck yes
add responder policy pol1 'HTTP.REQ.URL.STARTSWITH("/~") && HTTP.REQ.URL.LENGTH.GT(2)' act1
bind responder global pol1 100

将主机名变体转换为规范主机名

您可以强制使用特定主机名来访问站点。例如,您可以强制使用 www.example.com 而不是示例 .com。

Apache mod_rewrite 解决方案,用于为在 80 以外的端口上运行的站点强制执行特定主机名


RewriteCond %{HTTP_HOST}   !^www.example.com
RewriteCond %{HTTP_HOST}   !^$
RewriteCond %{SERVER_PORT} !^80$
RewriteRule ^/(.*)         http://www.example.com:%{SERVER_PORT}/$1 [L,R]

用于为端口 80 上运行的站点强制执行特定主机名的 Apache mod_rewrite 解决方案


RewriteCond %{HTTP_HOST}   !^www.example.com
RewriteCond %{HTTP_HOST}   !^$
RewriteRule ^/(.*)         http://www.example.com/$1 [L,R]

Citrix ADC 解决方案,用于为在 80 以外的端口上运行的站点强制执行特定主机名


add responder action act1 redirect '"http://www.example.com:"+CLIENT.TCP.DSTPORT+HTTP.REQ.URL' -bypassSafetyCheck yes
add responder policy pol1 '!HTTP.REQ.HOSTNAME.CONTAINS("www.example.com")&&!HTTP.REQ.HOSTNAME.EQ("")&&!HTTP.REQ.HOSTNAME.PORT.EQ(80)&&HTTP.REQ.HOSTNAME.CONTAINS("example.com")' act1
bind responder global pol1 100 END

用于为端口 80 上运行的站点强制执行特定主机名的 Citrix ADC 解决方案


add responder action act1 redirect '"http://www.example.com"+HTTP.REQ.URL' -bypassSafetyCheck yes
add responder policy pol1  '!HTTP.REQ.HOSTNAME.CONTAINS("www.example.com")&&!HTTP.REQ.HOSTNAME.EQ("")&&HTTP.REQ.HOSTNAME.PORT.EQ(80)&&HTTP.REQ.HOSTNAME.CONTAINS("example.com")' act1
bind responder global  pol1 100 END

移动文档根目录

通常 Web 服务器的文档根目录基于 URL“/”。但是,文档根目录可以是任何目录。如果文档根目录从顶级“/”目录更改为另一个目录,则可以将流量重定向到文档根目录。

在以下示例中,您将文档根目录从/更改为 /e/www。前两个示例简单地将一个字符串替换为另一个字符串。第三个示例更具普遍性,因为除了替换根目录之外,它还保留了 URL 的其余部分(路径和查询字符串),例如,将 /example/file.html 重定向到 /e/www/example/file.html。

用于移动文档根目录的 Apache mod_rewrite 解决方案


RewriteEngine on
RewriteRule   ^/$  /e/www/  [R]

用于移动文档根目录的 Citrix ADC 解决方案


add responder action act1 redirect '"/e/www/"' -bypassSafetyCheck yes
add responder policy pol1 'HTTP.REQ.URL.EQ("/")' act1
bind responder global pol1 100

用于移动文档根目录并将路径信息附加到请求的 Citrix ADC 解决方案


add responder action act1 redirect '"/e/www"+HTTP.REQ.URL' -bypassSafetyCheck yes
add responder policy pol1 '!HTTP.REQ.URL.STARTSWITH("/e/www/")' act1
bind responder global pol1 100 END

将主目录移动到新的 Web 服务器

您可能希望将发送到 Web 服务器上的主目录的请求重定向到其他 Web 服务器。例如,如果一个新的 Web 服务器随着时间的推移替换旧的 Web 服务器,当您将主目录迁移到新位置时,您需要将迁移的主目录的请求重定向到新的 Web 服务器。

在以下示例中,新 Web 服务器的主机名是新服务器。

用于重定向到另一个 Web 服务器的 Apache mod_rewrite 解决方案


RewriteRule   ^/(.+)  http://newserver/$1     [R,L]

用于重定向到另一个 Web 服务器的 Citrix ADC 解决方案(方法 1)


add responder  action act1 redirect '"http://newserver"+HTTP.REQ.URL' -bypassSafetyCheck yes
add responder policy pol1 'HTTP.REQ.URL.REGEX_MATCH(re#^/(.+)#)'   act1
bind responder global pol1 100 END

用于重定向到另一个 Web 服务器的 Citrix ADC 解决方案(方法 2)


add responder  action act1 redirect '"http://newserver"+HTTP.REQ.URL' -bypassSafetyCheck yes
add responder policy pol1 'HTTP.REQ.URL.LENGTH.GT(1)' act1
bind responder global pol1 100 END

使用结构化主目录

通常,具有成千上万用户的站点具有结构化的主目录布局。例如,每个主目录可能位于使用用户名的第一个字符命名的子目录下。例如,jsmith(/~jsmith/anypath)的主目录可能是/home /j/smth/.www /anypath,并且 rvalveti(/~rvalveti/anypath)的主目录可能是/home /r/rvalveti/.www /任何路径。

以下示例将请求重定向到主目录。

结构化主目录的 Apache mod_rewrite 解决方案

RewriteRule   ^/~(([a-z])[a-z0-9]+)(.*)  /home/$2/$1/.www$3

面向结构化主目录的 Citrix ADC 解决方案

面向结构化主目录的 Citrix ADC 解决方案


add rewrite action act1 replace 'HTTP.REQ.URL'  '"/home/"+ HTTP.REQ.URL.AFTER_STR("~").PREFIX(1)+"/"+ HTTP.REQ.URL.AFTER_STR("~").BEFORE_STR("/")+"/.www"+HTTP.REQ.URL.SKIP('/',1)'  -bypassSafetyCheck yes
add rewrite policy pol1  'HTTP.REQ.URL.PATH.STARTSWITH("/~")' act1
bind rewrite global pol1 100

将无效 URL 重定向到其他 Web 服务器

如果 URL 无效,则应将其重定向到另一个 Web 服务器。例如,如果 URL 中命名的文件不存在于 URL 中命名的服务器上,则应重定向到另一个 Web 服务器。

在 Apache 上,您可以使用 mod_rewrite 执行此检查。在 Citrix ADC 上,HTTP 标注可以通过在服务器上运行脚本来检查服务器上的文件。在以下 Citrix ADC 示例中,名为 file_check.cgi 的脚本处理 URL,并使用此信息检查服务器上是否存在目标文件。脚本返回 TRUE 或 FALSE,Citrix ADC 使用脚本返回的值来验证策略。

除了执行重定向外,Citrix ADC 还可以添加自定义标头,或者如第二个 Citrix ADC 示例所示,它可以在响应正文中添加文本。

如果 URL 错误,则用于重定向的 Apache mod_rewrite 解决方案


RewriteCond   /your/docroot/%{REQUEST_FILENAME} !-f
RewriteRule   ^(.+)      http://webserverB.com/$1 [R]

如果 URL 错误,则用于重定向的 Citrix ADC 解决方案(方法 1)


add HTTPCallout Call
set policy httpCallout Call -IPAddress 10.102.59.101 -port 80 -hostExpr '"10.102.59.101"' -returnType BOOL -ResultExpr 'HTTP.RES.BODY(100).CONTAINS("True")'  -urlStemExpr '"/cgi-bin/file_check.cgi"'   -parameters query=http.req.url.path -headers Name("ddd")
add responder action act1 redirect '"http://webserverB.com"+HTTP.REQ.URL' -bypassSafetyCheck yes
add responder policy pol1 '!HTTP.REQ.HEADER("Name").EXISTS  &&  !SYS.HTTP_CALLOUT(call)' act1
bind responder global pol1 100

如果 URL 错误,则用于重定向的 Citrix ADC 解决方案(方法 2)


add HTTPCallout Call
set policy httpCallout Call -IPAddress 10.102.59.101 -port 80 -hostExpr '"10.102.59.101"' -returnType BOOL -ResultExpr 'HTTP.RES.BODY(100).CONTAINS("True")'  -urlStemExpr '"/cgi-bin/file_check.cgi"'   -parameters query=http.req.url.path -headers Name("ddd")
add responder  action act1 respondwith  '"HTTP/1.1 302 Moved Temporarily\r\nLocation: http://webserverB.com"+HTTP.REQ.URL+"\r\n\r\nHTTPCallout Used"' -bypassSafetyCheck yes
add responder policy pol1 '!HTTP.REQ.HEADER("Name").EXISTS  &&  !SYS.HTTP_CALLOUT(call)' act1
bind responder global pol1 100

基于时间重写 URL

您可以根据时间重写 URL。以下示例将例如 .html 的请求更改为 .day.html 或 .夜.html,具体取决于一天中的时间。

基于时间重写 URL 的 Apache mod_rewrite 解决方案


RewriteCond   %{TIME_HOUR}%{TIME_MIN} >0700
RewriteCond   %{TIME_HOUR}%{TIME_MIN} <1900
RewriteRule   ^example.html$ example.day.html [L]
RewriteRule   ^example.html$ example.night.html

用于基于时间重写 URL 的 Citrix ADC 解决方案


add rewrite action act1 insert_before 'HTTP.REQ.URL.PATH.SUFFIX('.',0)' '"day."'
add rewrite action act2  insert_before 'HTTP.REQ.URL.PATH.SUFFIX('.',0)' '"night."'
add rewrite  policy pol1 'SYS.TIME.WITHIN(LOCAL 07h 00m,LOCAL 18h 59m)' act1
add rewrite policy pol2 'true'  act2
bind rewrite global pol1 101
bind rewrite global pol2 102

重定向到新文件名(用户不可见)

如果重命名网页,则可以继续支持旧 URL 以实现向后兼容,同时防止用户识别该页已重命名。

在下面的前两个示例中,基本目录是 /~quux/。第三个示例适用于任何基本目录以及 URL 中查询字符串的存在。

用于在固定位置管理文件名更改的 Apache mod_rewrite 解决方案


RewriteEngine  on
RewriteBase    /~quux/
RewriteRule    ^foo.html$  bar.html

用于管理固定位置文件名更改的 Citrix ADC 解决方案


add rewrite action act1 replace 'HTTP.REQ.URL.AFTER_STR("/~quux").SUBSTR("foo.html")' '"bar.html"'
add rewrite policy pol1 'HTTP.REQ.URL.ENDSWITH("/~quux/foo.html")' act1
bind rewrite global pol1 100

用于管理文件名更改的 Citrix ADC 解决方案,而不考虑 URL 中的基本目录或查询字符串


add rewrite action act1 replace 'HTTP.REQ.URL.PATH.SUFFIX('/',0)' '"bar.html"'
Add rewrite policy pol1 'HTTP.REQ.URL.PATH.CONTAINS("foo.html")' act1
Bind rewrite global pol1 100

重定向到新文件名(用户可见的 URL)

如果您重命名网页,您可能希望继续支持旧 URL 以实现向后兼容性,并允许用户通过更改浏览器中显示的 URL 来看到该页面已重命名。

在下面的前两个示例中,当基本目录为 /~quux/ 时发生重定向。第三个示例适用于任何基本目录以及 URL 中查询字符串的存在。

用于更改浏览器中显示的文件名和 URL 的 Apache mod_rewrite 解决方案


RewriteEngine on
RewriteBase    /~quux/
RewriteRule    ^old.html$ new.html  [R]

用于更改浏览器中显示的文件名和 URL 的 Citrix ADC 解决方案


add responder action act1 redirect 'HTTP.REQ.URL.BEFORE_STR("foo.html")+"new.html"' -bypassSafetyCheck yes
add responder policy pol1 'HTTP.REQ.URL.ENDSWITH("/~quux/old.html")' act1
bind responder global pol1 100

Citrix ADC 解决方案,用于更改浏览器中显示的文件名和 URL,而不考虑 URL 中的基本目录或查询字符串


add responder action act1 redirect 'HTTP.REQ.URL.PATH.BEFORE_STR("old.html")+"new.html"+HTTP.REQ.URL.AFTER_STR("old.html")' -bypassSafetyCheck yes
add responder policy pol1 'HTTP.REQ.URL.PATH.CONTAINS("old.html")' act1
bind responder global pol1 100

容纳与浏览器相关的内容

为了适应特定于浏览器的限制(至少对于重要的顶级页面),有时需要对浏览器类型和版本设置限制。例如,您可能需要为最新的 Netscape 变体设置最大版本,为 Lynx 浏览器设置最低版本,为所有其他版本设置平均功能版本。

以下示例作用于 HTTP 标头“用户代理”,因此,如果此标头以“Mozilla/3”开头,则页面 Myypage.html 将被重写为 MyPage.ns.html。如果浏览器是 Lynx 或 Mozilla 版本 1 或 2,则该 URL 将变为 MyPage.20.html。所有其他浏览器接收页面 MyPage.32.html。

针对特定于浏览器的设置的 Apache mod_rewrite 解决方案


RewriteCond %{HTTP_USER_AGENT}  ^Mozilla/3.*
RewriteRule ^MyPage.html$ MyPage.NS.html [L]
RewriteCond %{HTTP_USER_AGENT}  ^Lynx/.* [OR]
RewriteCond %{HTTP_USER_AGENT}  ^Mozilla/[12].*
RewriteRule ^MyPage.html$ MyPage.20.html [L]
RewriteRule ^fMyPage.html$ MyPage.32.html [L]
Citrix ADC solution for browser-specific settings
add patset pat1
bind patset pat1 Mozilla/1
bind Patset pat1 Mozilla/2
bind patset pat1 Lynx
bind Patset pat1 Mozilla/3
add rewrite action act1 insert_before 'HTTP.REQ.URL.SUFFIX' '"NS."'
add rewrite action act2 insert_before 'HTTP.REQ.URL.SUFFIX' '"20."'
add rewrite action act3 insert_before 'HTTP.REQ.URL.SUFFIX' '"32."'
add rewrite policy pol1 'HTTP.REQ.HEADER("User-Agent").STARTSWITH_INDEX("pat1").EQ(4)' act1
add rewrite policy pol2 'HTTP.REQ.HEADER("User-Agent").STARTSWITH_INDEX("pat1").BETWEEN(1,3)' act2
add rewrite policy pol3 '!HTTP.REQ.HEADER("User-Agent").STARTSWITH_ANY("pat1")' act3
bind rewrite global pol1 101 END
bind rewrite global pol2 102 END
bind rewrite global pol3 103 END

阻止机器人访问

您可以阻止机器人从特定目录或一组目录中检索页面,以减轻来自这些目录的流量。您可以根据特定位置限制访问,也可以根据用户代理 HTTP 头中的信息阻止请求。

在以下示例中,要阻止的 Web 位置是 /~quux/foo/arc/,要阻止的 IP 地址是 123.45.67.8 和 123.45.67.9,机器人的名称是 BadRobot 的名称。

用于阻止路径和用户代理标头的 Apache mod_rewrite 解决方案


RewriteCond %{HTTP_USER_AGENT}   ^NameOfBadRobot.*
RewriteCond %{REMOTE_ADDR}       ^123.45.67.[8-9]$
RewriteRule ^/~quux/foo/arc/.+   -   [F]

用于阻止路径和用户代理标头的 Citrix ADC 解决方案


add responder action act1 respondwith '"HTTP/1.1 403 Forbidden\r\n\r\n"'
add responder policy pol1 'HTTP.REQ.HEADER("User_Agent").STARTSWITH("NameOfBadRobot")&&CLIENT.IP.SRC.EQ(123.45.67.8)&&CLIENT.IP.SRC.EQ(123.45.67.9) && HTTP.REQ.URL.STARTSWITH("/~quux/foo/arc")' act1
bind responder global pol1 100

阻止访问内联图像

如果您发现人们经常前往您的服务器复制内联图形以供自己使用(并产生不必要的流量),则可能需要限制浏览器发送 HTTP Referer 标头的能力。

在以下示例中,图形位于 示例 中。

用于阻止访问内联映像的 Apache mod_rewrite 解决方案


RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://www.quux-corp.de/~quux/.\*$
RewriteRule .\*.gif$ - [F]

用于阻止访问内联映像的 Citrix ADC 解决方案


add patset pat1
bind patset pat1 .gif
bind patset pat1 .jpeg
add responder action act1 respondwith '"HTTP/1.1 403 Forbidden\r\n\r\n"'
add responder policy pol1 '!HTTP.REQ.HEADER("Referer").EQ("") && !HTTP.REQ.HEADER("Referer").STARTSWITH("http://www.quux-corp.de/~quux/")&&HTTP.REQ.URL.ENDSWITH_ANY("pat1")' act1
bind responder global pol1 100

创建无扩展链接

要防止用户了解服务器端的应用程序或脚本详细信息,可以隐藏用户的文件扩展名。为此,您可能需要支持无扩展名链接。您可以通过使用重写规则将扩展添加到所有请求或选择性地向请求添加扩展来实现此行为。

以下示例中的前两个显示了向所有请求 URL 添加扩展名。在最后一个示例中,添加了两个文件扩展名之一。请注意,在最后一个示例中,mod_rewrite 模块可以很容易地找到文件扩展名,因为这个模块驻留在 Web 服务器上。相比之下,Citrix ADC 必须调用 HTTP 标注来检查 Web 服务器上请求文件的扩展名。基于标注响应,Citrix ADC 将 .html 或 .php 扩展名添加到请求 URL 中。

注意

在第二个 Citrix ADC 示例中,HTTP 标注用于查询服务器上托管的名为 file_check.cgi 的脚本。此脚本检查标注中提供的参数是否为有效的文件名。

Apache mod_rewrite 解决方案,用于向所有请求添加一个 .php 扩展名


RewriteRule ^/?([a-z]+)$ $1.php [L]

用于向所有请求添加 .php 扩展名的 Citrix ADC 策略


add rewrite action act1 insert_after 'HTTP.REQ.URL' '".php"'
add rewrite policy pol1 'HTTP.REQ.URL.PATH.REGEX_MATCH(re#^/([a-z]+)$#)' act1
bind rewrite global pol1 100

用于向请求添加 .html 或 .php 扩展名的 Apache mod_rewrite 解决方案


RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^/?([a-zA-Z0-9]+)$ $1.php [L]
RewriteCond %{REQUEST_FILENAME}.html –f
RewriteRule ^/?([a-zA-Z0-9]+)$ $1.html [L]

用于向请求添加 .html 或 .php 扩展名的 Citrix ADC 策略


add HTTPCallout Call_html
add HTTPCallout Call_php
set policy httpCallout Call_html -IPAddress 10.102.59.101 -port 80 -hostExpr '"10.102.59.101"' -returnType BOOL -ResultExpr 'HTTP.RES.BODY(100).CONTAINS("True")'  -urlStemExpr '"/cgi-bin/file_check.cgi"'   -parameters query=http.req.url+".html"
set policy httpCallout Call_php -IPAddress 10.102.59.101 -port 80 -hostExpr '"10.102.59.101"' -returnType BOOL -ResultExpr 'HTTP.RES.BODY(100).CONTAINS("True")'  -urlStemExpr '"/cgi-bin/file_check.cgi"' -parameters query=http.req.url+".php"
add patset pat1
bind patset pat1 .html
bind patset pat1 .php
bind patset pat1 .asp
bind patset pat1 .cgi
add rewrite  action act1 insert_after 'HTTP.REQ.URL.PATH'  '".html"'
add rewrite  action act2 insert_after "HTTP.REQ.URL.PATH"  '".php"'
add rewrite policy pol1 '!HTTP.REQ.URL.CONTAINS_ANY("pat1") && SYS.HTTP_CALLOUT(Call_html)' act1
add rewrite policy pol2 '!HTTP.REQ.URL.CONTAINS_ANY("pat1") && SYS.HTTP_CALLOUT(Call_php)' act2
bind rewrite global pol1 100 END
bind rewrite global pol2 101 END

将工作 URI 重定向到新格式

假设您有一组类似于以下内容的工作 URL:


/index.php?id=nnnn

要将这些 URL 更改为 /nnnn 并确保搜索引擎将其索引更新为新 URI 格式,您需要执行以下操作:

  • 将旧 URI 重定向到新的 URI,以便搜索引擎更新其索引。
  • 将新的 URI 重写回旧的 URI,以便 index.php 脚本正常运行。

为此,您可以将标记代码插入到查询字符串中(确保访客看不到标记代码),然后删除 index.php 脚本的标记代码。

仅当查询字符串中不存在标记时,以下示例将从旧链接重定向到新格式。使用新格式的链接将重新写回旧格式,并将标记添加到查询字符串。

Apache mod_rewrite 解决方案


RewriteCond %{QUERY_STRING} !marker
RewriteCond %{QUERY_STRING} id=([-a-zA-Z0-9_+]+)
RewriteRule ^/?index.php$ %1? [R,L]
RewriteRule ^/?([-a-zA-Z0-9_+]+)$  index.php?marker&id=$1 [L]
Citrix ADC solution
add responder action act_redirect redirect 'HTTP.REQ.URL.PATH.BEFORE_STR("index.php")+HTTP.REQ.URL.QUERY.VALUE("id")' -bypassSafetyCheck yes
add responder policy pol_redirect '!HTTP.REQ.URL.QUERY.CONTAINS("marker")&& HTTP.REQ.URL.QUERY.VALUE("id").REGEX_MATCH(re/[-a-zA-Z0-9_+]+/) && HTTP.REQ.URL.PATH.CONTAINS("index.php")' act_redirect
bind responder global pol_redirect 100 END
add rewrite action act1 replace 'HTTP.REQ.URL.PATH.SUFFIX('/',0)' '"index.phpmarker&id="+HTTP.REQ.URL.PATH.SUFFIX('/',0)' -bypassSafetyCheck yes
add rewrite policy pol1 '!HTTP.REQ.URL.QUERY.CONTAINS("marker")'  act1
bind rewrite global pol1 100 END

确保安全服务器用于所选页面

若要确保所选网页只使用安全服务器,可以使用以下 Apache mod_rewrite 代码或 Citrix ADC 响应程序策略。

Apache mod_rewrite 解决方案


RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^/?(page1|page2|page3|page4|page5)$  https://www.example.com/%1 [R,L]

使用正则表达式的 Citrix ADC 解决方案


add responder action res_redirect redirect  '"https://www.example.com"+HTTP.REQ.URL' -bypassSafetyCheck yes
add responder policy pol_redirect '!CLIENT.TCP.DSTPORT.EQ(443)&&HTTP.REQ.URL.REGEX_MATCH(re/page[1-5]/)'  res_redirect
bind responder global pol_redirect 100 END

使用模式集的 Citrix ADC 解决方案


add patset pat1
bind patset pat1 page1
bind patset pat1 page2
bind patset pat1 page3
bind patset pat1 page4
bind patset pat1 page5
add responder action res_redirect redirect  '"https://www.example.com"+HTTP.REQ.URL' -bypassSafetyCheck yes
add responder policy pol_redirect '!CLIENT.TCP.DSTPORT.EQ(443)&&HTTP.REQ.URL.CONTAINS_ANY("pat1")'  res_redirect
bind responder global pol_redirect 100 END

将 Apache mod_rewrite 规则迁移到默认语法

本文中包含的内容