顯示具有 apache 標籤的文章。 顯示所有文章
顯示具有 apache 標籤的文章。 顯示所有文章

2014年4月21日 星期一

X-Frame-Options 是什麼?

X-Frame-Options 是一個 HTTP 標頭 (header),用來告訴瀏覽器這個網頁是否可以放在 iFrame 內

1. X-Frame-Options: DENY
2. X-Frame-Options: SAMEORIGIN
3. X-Frame-Options: ALLOW-FROM http://www.facebook.com/

第一個例子告訴瀏覽器不要 (DENY) 把這個網頁放在 iFrame 內,通常的目的就是要幫助用戶對抗點擊劫持。
第二個例子告訴瀏覽器只有當架設 iFrame 的網站與發出 X-Frame-Options 的網站相同,才能顯示發出 X-Frame-Options 網頁的內容。
第三個例子告訴瀏覽器這個網頁只能放在 http://www.facebook.com/ 網頁架設的 iFrame 內。
不指定 X-Frame-Options 的網頁等同表示它可以放在任何 iFrame 內。
X-Frame-Options 可以保障你的網頁不會被放在惡意網站設定的 iFrame 內,令用戶成為點擊劫持的受害人,它剛在今年 10 月成為業界標準,IE8、Firefox、Safari、和 Chrome 都支援 X-Frame-Options。 
來源

2010年6月29日 星期二

[LAMP]SSL介紹

SSL介紹:出處
SSL(Secure Socket Layer)是Netscape所提出來的資料保密協定,採用了RC4、MD5,以及RSA等加密演算法。


網路上需要確定網站真的是那個網站,所以SSL也具備認證的機能。SSL是以金字塔的結構
組成,最下層的是一般的伺服器,它們經由向上跟CA申請取得SSL的憑證,CA會在SSL相關檔案上籤名,CA是具有公信力和認證能力的機構,CA必須向上跟RootCA(如政府機構等)申請。當使用者連結具SSL的服務時,伺服器會傳送憑證給使用者,使用端的程式接收到憑證後會向CA確認憑證,若CA確認這個憑是它們簽發的則會回傳給使用端正確的訊息。
具有SSL功能的網站可以向 世界少數幾個發證機構(例如目前最大的VeriSign或第二大的Thawte兩家認證公司)申請,經過嚴格的文件證明確認後,才能取得國際認可(較新版 的MSIE或Netscape瀏覽軟體會自動認得)的電子認證。



所有 SSL憑證都是發給公司或是法人,典型的 SSL 憑證將包括您的網域名稱(domain name)、您的公司名稱(company name)、您的住址(address)、您的所在城市(city)、您的省份(state)和您的國家(country),它也包含了憑證的到期日和負責核發此憑證的發證中心詳細資料。當一個瀏覽器連結到一個安全網站時,它將收到這個網站的SSL憑證並且檢驗它是否過期、它是否是已經被瀏覽器信任的發證中心所核發的,以及它是否如核發時 所登記的內容被該網站使用,假如有任何一項檢查不通過,瀏覽器將顯示一個警告訊息給使用者。



在Ubuntu上安裝 apache+mysql+php+openssl
sudo tasksel install lamp-server
安裝 lamp (apache mysql php)

sudo apt-get install mysql-admin mysql-gui-tools-common mysql-query-browser
安裝mysql的管理介面

sudo apt-get install -y php5-gd
安裝GD庫

sudo apt-get install -y openssl
安裝Openssl

sudo apt-get install -y ssl-cert
安裝簽署憑證的工具

sudo a2enmod ssl
安裝ssl模組

sudo cp /etc/apache2/sites-available/default /etc/apache2/sites-available/ssl
sudo ln -s /etc/apache2/sites-available/ssl /etc/apache2/sites-enabled/ssl
複製一份預設擋供ssl用,並且用ln建立連結(捷徑)至sites-enabled/ssl

sudo vim /etc/apache2/sites-enabled/ssl
在以下位置後面加入紅色的設定值

NameVirtualHost *:443

sudo vim /etc/apache2/sites-enabled/default
在以下位置後面加入紅色的設定值

NameVirtualHost *:80
SSLEngine On
SSLCerficationFile /etc/apache2/etc/apache.pem

sudo vim /usr/sbin/make-ssl-cert
將"-keyout $output"改成"-keyout $output -days 3650"即可將憑證有效時間改成10年

sudo mkdir /etc/apache2/ssl
建立ssl憑證所擺放目錄

sudo make-ssl-cert /usr/share/ssl-cert/ssleay.cnf /etc/apache2/etc/apache.pem

make-ssl-cert is a wrapper of OpenSSL
依照指示輸入憑證相關訊息,即可產生自簽的電子證書!

sudo /etc/init.d/apache2 force-reload
重新載入配置

sudo /etc/init.d/apache2 restart
重新啟動Apache2
產生自簽的CA
產生自簽的CA的意義是,自己架設一個CA,並為自己的伺服器的憑證簽名。則使用端收到憑證時,會向CA確定,這時就用自己架的CA去確認說憑證是有效的。當然這樣是沒有公信力的,而且把自己架的伺服器登記為CA需要手動加入,一般這樣做都是為了測試用。



參考以下連結

http://wiki.ubuntu.org.cn/OpenSSL
主要做兩件事情

第一件是架CA:Creating the Certificate Authority

第二件是架server:Creating a Self-Signed Server Certificate

並使用自己的CA為它簽名

2010年6月28日 星期一

「引用」Apache 設定筆記

出處: http://yes.dyndns.tv:84/dom/blog/apache2.htm

這邊也有更詳盡安裝教學...
apache 是個功能強大的 web server,所以它可設定調校的東西很多,一定要做個筆記紀錄下來,才不會日後想要某些功能卻不會設定。
本文環境: Linux debian 系統, apache2 版。 (apache1.3 是舊版有許多地方的設定不同不適用2版的設定方法)
以下內容,紅字部份皆為指令或是您需要修改的內容 ,藍字部份則為設定檔內容。

1.安 裝、2.設 定檔介紹、3.基 本設定、4.目 錄加密碼保護、5.IP 鎖定、6.Rewrite 功能、7.頻 寬限制、8.SSL 連線、9.Proxy 功能、10.啟 用Cache

1.安裝apache2

若你在一開始安裝未勾選apache,之後也可下指令來安裝
apt-get install apache2
↑這只是單純的安裝 apache 而已,若你需要 php 的支援,請用下面指令
apt-get install apache2 libapache2-mod-php5 php5-cli php5-common php5-cgi

2.設定檔介紹

先介紹一下 debian 內的 apache 設定檔,在 windows 平台上的 apache 設定檔,可能由 httpd.conf 就全都包了。
但 debian 將 httpd.conf 很多設定內容分離出來了。
/etc/apache2/apache2.conf    這是apache 的全域設定
/etc/apache2/httpd.conf    內容為空,傳統的設定檔,為相容於其它版本的設定
/etc/apache2/ports.conf    監聽 port 的設定
/etc/apache2/mods-available/    所有可用的模組( module)
/etc/apache2/mods-enabled/    已啟用的模組 (可用指令 a2enmod、a2dismod 來啟用、停用模組)
/etc/apache2/sites-available/    所有可用虛擬站台
/etc/apache2/sites-enabled/    己啟用的虛擬站台 (指令 a2ensite、a2dissite 可啟用、停用虛擬站台)
相關指令
啟動、停止、重啟 apache 等指令
/etc/init.d/apache2 start | stop | restart

apache 設定檔測試指令 (apache 設定檔的語法若寫錯,會使apache無法啟動,可用此指令測試)
apache2ctl configtest
/etc/rc.d/init.d/httpd start | stop | restart
↑以上是在Fedora、CentOS的指令,在debian不適用

開機就啟動的設定在
/etc/default/apache2
預設是開機啟動 (NO_START=0),不想開機啟動請改成 1



apache2.conf說明與注意事項:
(1).不是使用傳統的 httpd.conf 而以 /etc/apache2/apache2.conf 取代之。
(2).Listen 80 port位的設定也不同於一般版本的設定
在apache2.conf 此檔內有一行 Include /etc/apache2/ports.conf
請 vim /etc/apache2/ports.conf 加入你要監聽的port 位
(3).預設的使用者與群組
User ${APACHE_RUN_USER}
Group ${APACHE_RUN_GROUP}


apache 啟動的身份與群組,在 debian 內的身份與群組皆為 www-data

3.基本設定

系統裝好後,已有一基本站台,編輯設定檔內容
vim /etc/apache2/sites-available/default
==========================================

ServerAdmin webmaster@localhost

DocumentRoot /var/www/
#預設網站的根目錄

#重覆設定了可將它刪除

Options FollowSymLinks
AllowOverride None

#↓定義該目錄的權限

Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all


#↓設定cgi-bin執行目錄,若你的站用不到 cgi 可將此段刪除或前面加 # 號停用
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/

AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all

# log 檔設定
ErrorLog /var/log/apache2/error.log
LogLevel warn
CustomLog /var/log/apache2/access.log combined

#說明檔,你應該用不著可以將它刪了吧
Alias /doc/ "/usr/share/doc/"

Options Indexes MultiViews FollowSymLinks
AllowOverride None
Order deny,allow
Deny from all
Allow from 127.0.0.0/255.0.0.0 ::1/128



==========================================
重啟 apache
/etc/init.d/apache2 restart
或
apache2ctl restart

4.目錄加密碼保護

要對目錄加密碼保護有兩種方法,一是直接設定在 apache 檔內。二是在該目錄底下設定一個 .htaccess 檔。底下主要介紹第二種方法。
a.編輯 apache 設定檔
vim /etc/apache2/apache2.conf
例如,我們有兩個目錄要加密碼保護,分別為 /awstats 和 /cacti
請在 apache 設定檔內加入底下內容
#底下為受密碼保護的目錄

    AllowOverride AuthConfig
    Order allow,deny
    Allow from all


    AllowOverride AuthConfig
    Order allow,deny
    Allow from all

那個紅字就是整個設定的重點
另外還要檢查 apache2.conf 設定檔內是否還有對同一目錄的設定,若有請把它加#號,否則密碼保護無法設定成功。
例如: /awstats 是對應到 /var/www/84/awstats/wwwroot 這目錄,但這目錄也有針對它的設定必須將其取消
否則密碼保護不會設定成功。
#
#    Options None
#    AllowOverride None
#    Order allow,deny
#    Allow from all
#


設完之後重啟 apache
/etc/init.d/apache2 restart


b.建密碼檔
建一密碼檔名為apache.passwd 存放在 /home/backup
htpasswd -c /home/backup/apache.passwd user1
接著輸入密碼 xxxxxxxx
在密碼檔內建第二個使用者 (不加 -c 參數了)
htpasswd /home/backup/apache.passwd user2

註:user1和user2為你自訂的使用者帳號,xxxxx為你自訂的密碼

改變檔案屬性
chown www /home/backup/apache.passwd
chgrp users /home/backup/apache.passwd


c.在要被保護的目錄下建.htaccess檔
先進到你要密碼保護的目錄底下
cd /var/www/84/awstats/wwwroot/
vim .htaccess
=====加入以下內容==================
AuthName     "This is Private directory"
Authtype     Basic
AuthUserFile
/home/backup/apache.passwd
require user
user1 user2
#require:後面接可以使用的帳號。
#如果要讓該密碼檔內的使用者都能夠登入,就改成『require valid-user』即可

===================================
改變檔案屬性
chown www .htaccess
chgrp users .htaccess
然後再把此檔copy到你要密碼保護的 另一個目錄底下去
cp .htaccess /usr/share/cacti/site

參考資料

5.IP鎖定

除了加密碼保護以外,我們也可以用鎖定IP的方式來增加安全性
例如:我有一站台目錄是指向 /var/www/syscp 這站台很重要,不能讓別人隨便進來,除了密碼保護外可能還不夠,那麼我們就可以鎖定只有哪些 IP 可以訪問這個站台。
vim /etc/apache2/sites-enabled/000-default
-----------------------------------------------

    Options Indexes FollowSymLinks MultiViews
    AllowOverride None
   
Order deny,allow
    deny from all
    allow from 192.168.0.0/24 220.130.30.39

------------------------------------------------
以上設定為鎖定 syscp 後台管理頁面,只允許192.168.0.0這個網段和這個 220.130.30.39 IP可以登入
注意: 這兩行的上下順序若是相反的
    deny from all
    allow from 192.168.0.0/24 220.130.30.39

變成底下這樣 (deny 在最後一行)
    allow from 192.168.0.0/24 220.130.30.39
    deny from all

這樣就等於是將整個關閉網站了,沒有任何人可以訪問了,因為 deny 在最後才被套用。

6.Rewrite功能

簡單介紹一下這功能,就是當點  abc.com/aa.htm 這網址進來時,可以設定讓它變成 cde.com/aa.htm 的效果
啟用 rewrite 模組
a2enmod rewrite
apache2ctl restart
rewrite 的規則可寫在 apache 設定檔內,也可寫在該目錄底下(.htaccess)。每一筆 rewrite 都會造成 apache 和 cpu 的負擔,所以 rewrite 的規則應儘量減少。
建議最好寫在該目錄底下才能減輕負載,在 user 存取該目錄時,rewrite 才會起作用。若將rewrite的規則寫在網站的根目錄,則 user 在存取站上的每一個檔案時都會去比對 rewrite 的規則,會對系統效能有所影響,這在看 rewrite 的 log 檔時可觀察到。
rewrite 規則得用正規表示法來寫
a.先介紹寫在 apache 設定檔內

RewriteLogLevel 1
#設定 rewrite log 檔的等級,預設為 0 不記錄。 設為 3 以上會降低 apache 效能

Rewritelog /var/log/apache2/80_rewrite.log
#設定 rewrite log 檔位置

RewriteEngine On
# ↑這裡若設為 off 則將 rewrite 的功能全關閉

RewriteRule /sound/(.*) http://192.168.0.1/test/sound/$1
#↑ /sound/ 底下所有的檔案全轉到後面那個網址去,最後面的那個 $1 是變數1,化表前面括號裡的東西  ( .*)  點星號代表任何檔案

RewriteRule /book/(.*) http://192.168.0.1/test/book/$1
RewriteRule ^/(.*).wmv$ http://192.168.0.1/test/$1.wmv
# ↑ 根目錄底下的 .wmv 檔全轉到後面那個網址去。  ^/ 為 斜線開頭的意思  .wmv$ 為 wmv結尾的意思。


Options Indexes
FollowSymLinks MultiViews
AllowOverride all
Order allow,deny
allow from all



b.寫在 .htaccess
好處是可以不用重啟 apache 和減輕系統的負載
vim /var/www/80/video/.htaccess
RewriteEngine On
RewriteRule (.*\.htm$) $1 [S=1]
#如果符合 *.htm 的檔案,就跳過底下第一條規則
RewriteRule (.*) http://192.168.0.1/80port/video/$1
#將所有的檔案都轉到另一個網址去下載



vim /var/www/80/flash/.htaccess
RewriteEngine On
RewriteRule (.*)\.flv$ http://192.168.0.1/80port/flash/$1.flv
#將所有的 *.flv 檔案都轉到另一個網址去下載

何時使用.htaccess中的重寫規則定義?
假如你對你的的網站內容所在的服務器沒有管理員權限,或者你的網站放在ISP的服務器上託管等等條件下,你無法改寫主配置文件,然而你可以對你的WEB站 點內容所在的目錄有寫權限,則你可以設置自己的.htaccess 文件達到同樣的目的。但你需要確定主配置文件中對你的網站所在的目錄定義了下面的內容:

Options Indexes FollowSymLinks
AllowOverride all


否則你的.htaccess不會工作。
參考資料:
設置圖片防盜連功能、使 用漂亮的網址、重 寫規則的常見應用

7.頻寬限制

安裝和啟用頻寬限制模組
apt-get install libapache2-mod-bw
a2enmod bw

vim /etc/apache2/sites-available/default
然後在你的虛擬站台裡加入以下參數
-------------------------------------------------

    DocumentRoot "/home/movie"
    ServerName xxx.com

    #頻寬限制
    BandWidthModule On
    ForceBandWidthModule On
    Bandwidth all 102400
    #102400 ==>100K 限制
    #MaxConnection all 10
    #限制連線數 10

       
        Options....
        ...etc
       


-------------------------------------------------
改完後記得重啟 apache
參考資料: 花栗鼠柑仔店、AppleBoy
按 我展開mod_bw其它參數介紹的內容

 

8.SSL連線

debian 4 和 debian 5 的設定法有些不一樣。
debian 4 的設定法
a.安裝ssl-cert
apt-get install ssl-cert
由於 Etch (4.0) 版本未能提供慣用的 apache2-ssl-certificate 命令,因此若你的 Debian 版本是 Etch,你可以使用 make-ssl-cert 命令,安裝 ssl-cert 套件。
b.產生憑證
兩個方法,任選一種

make-ssl-cert /usr/share/ssl-cert/ssleay.cnf /etc/apache2/apache.pem
↑這會問你些問題,照回答即可,產生出來的憑證有效日期為一個月
openssl req $@ -new -x509 -days 365 -nodes -out /etc/apache2/apache.pem -keyout /etc/apache2/apache.pem
這會產生有效期限一年的RSA key,路徑可以自己決定。
接下來會有一段設定根憑證發行資訊的問題,適當的填一下就好了。
為了安全起見,請設定一下private key的權限:
# chmod 600 /etc/apache2/apache.pem
有的文章會叫你去安裝apache-ssl,不過這是apache 1.3的套件,並不適合

c.啟用 ssl module
a2enmod ssl
echo "Listen 443" >> /etc/apache2/ports.conf



然後在你的 443 虛擬站台內加上這兩行
SSLEngine on
SSLCertificateFile /etc/apache2/apache.pem

即可啟用 ssl 連線

========================================================================
範例:

NameVirtualHost *:443
NameVirtualHost *:80


ServerName earth.my.flat
DocumentRoot /var/www/
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined



ServerName earth.my.flat

DocumentRoot /var/www/
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined

SSLEngine on
SSLCertificateFile /etc/apache2/apache.pem



========================================================================
debian 5 設定方法
以下指令基於 debian 5,0 (lenny) 版環境測試成功。
啟用 ssl 模組
a2enmod ssl
啟用 ssl 虛擬站台
a2ensite default-ssl
安裝 ssl 套件
apt-get install openssl ssl-cert
重啟 apache
/etc/init.d/apache2 restart
測試
https://yourIP

補充說明:若你進入 https 網站後出現如下的錯誤訊息
SSL 收到含超出最大允許字串長度的記錄。
(錯誤碼: ssl_error_rx_record_too_long)

那表示你有可能是用 https://yourIP:port 這樣的網址進入,因為 https 預設是會導向443 port ,但你後面又指定了特殊的 port 會與 443 port 相衝突,解決方法就是把 port 移開,用  https://yourIP 這樣進入就可以了




參 考資料(英文)、ssl_error_rx_record_too_long
產生一張SSL證書、管理你的CA

Enable SSL on Apache 2.2 at debian





9.Proxy功能

啟用 proxy 模組
a2enmod proxy proxy_connect proxy_http
開放 proxy 權限
vim /etc/apache2/mods-available/proxy.conf
將 Deny from all 前標 # 號,並在其下一行加上這行文字 Allow from 127.0.0.1
這樣就能限制只有本機才能使用proxy,以提高安全性,然後在你的設定檔內加入底下這兩行
#人民報
ProxyPass /rmb http://www.renminbao.com/rmb/ smax=5 max=20

#明慧網
ProxyPass /mh http://minghui.org/mh/
ProxyPass /images http://minghui.org/images/
ProxyPass /pub http://minghui.org/pub/

#正見網
ProxyPass /zj http://zhengjian.org/zj/ smax=5 max=20
ProxyPass /news_images http://zhengjian.org/news_images/ smax=5 max=20


/etc/init.d/apache2 restart
然後用 http://192.168.0.150/rmb 就能看到別站的內容了

參考資料
Apache 的 Proxypass 指令詳解

若使用了 proxypass 之後,還要配合底下的 cache 才能減少本機向外部取資料的頻寬

10.啟用 cache

a2enmod cache
a2enmod disk_cache

vim /etc/apache2/mods-available/disk_cache.conf

CacheRoot /var/cache/apache2/mod_disk_cache
#cache 檔案的根目錄

CacheEnable disk /
#↑設定哪些目錄要做 cache
#CacheDirLevels 5
#↑定義緩存子目錄層數,缺省是1
CacheDirLength 5
#設置緩存子目錄名字的長度,缺省是1。即所有子目錄的名字都是由一個字母組成。
#↓每隔4小時檢查緩存區,如果已經超過CacheSize就刪除文件。缺省是4
#CacheGcInterval 4
#↑指定收垃圾 (Garbage Collection) 的動作間隔時間;單位是小時。不過根據 Apache2 文件,這個指令還 沒有被實作 。
#CacheDefaultExpire 86400
#cache保存時間(單位:秒) 預設為 3600 (1小時), 86400秒,為24小時
#CacheMaxExpire 154000
#cache保存最長時間(單位:秒)預設為 86400 秒(1天),若此期間都不曾被使用過,就會刪除,預設超過這時
CacheMaxFileSize 30000000
# byte, 3000 →3K, 3,000,000→3000K→3MB
#↑ 這裡設定的是,單一檔案cache的大小為 30MB

/etc/init.d/apache2 restart

參考資料:
IBM HTTP Server
apache的緩存mod_cache設置

修改httpd.conf這個文件
#一個連接的最大請求數量
MaxKeepAliveRequests 10000
#NT環境,只能配置這個參數來提供性能

#每個進程的線程數,最大1920。NT只啟動父子兩個進程,不能設置啟動多個進程
ThreadsPerChild 1900
每個子進程能夠處理的最大請求數
MaxRequestsPerChild 10000


LoadModule cache_module modules/mod_cache.so
LoadModule disk_cache_module modules/mod_disk_cache.so
LoadModule mem_cache_module modules/mod_mem_cache.so

CacheForceCompletion 100
CacheDefaultExpire 3600
CacheMaxExpire 86400
CacheLastModifiedFactor 0.1


CacheEnable disk C:/server/httpcache/diskcache
CacheRoot c:/server/httpcache/cacheroot
CacheSize 647680
CacheDirLength 4
CacheDirLevels 5
CacheGcInterval 4


CacheEnable mem C:/server/httpcache/memcache
MCacheSize 8192
MCacheMaxObjectCount 10000
MCacheMinObjectSize 1
MCacheMaxObjectSize 51200




####################################################
參考資料
mod_cache:
CacheEnable: 啟動 mod_cache,其後接兩個參數。第一個參數指定快取的種類,應設為 mem (記憶體快取) 或 disk (磁碟快取) 之其一;第二個參數指定使用快取的 URI 路徑,如果對整個網站 (或虛擬主機) 進行快取,簡單指定為根目錄(/) 即可。
CacheForceCompletion: 這個值指定當 HTTP request 被取消時,內容的產生動作要完成的百分比;預設是 60(%)。
CacheDefaultExpire: 指定快取的預設過期秒數;預設值是一小時 (3600)。
CacheMaxExpire: 指定快取最大的過期秒數;預設值是一天 (86400)。
CacheLastModifiedFactor: 用來從回應裡 Last Modified 資訊算出 expiredate。

計算方式是:
expire period (過期時距) = 最後更新後至今的時間間距 *CacheLastModifiedFactor
而
expire date = 目前時間 + expire period
不過無論如何,過期時間不能超過 CacheMaxExpire 的設定值。

mod_disk_cache:
CacheRoot: 指定磁碟快取所使用的目錄。
CacheSize: 以 KByte 為單位指定快取使用的磁碟空間大小。
CacheDirLength: 指定各目錄 (的鍵值) 存在於快取階層 (hierarchy) 中所使用的字元數。
CacheDirLevels: 指定快取的目錄層數; CacheDirLength 與此 CacheDirLevels設定值相乘不能超過 20。
CacheGcInterval: 指定收垃圾 (Garbage Collection) 的動作間隔時間;單位是小時。不過根據 Apache2 文件,這個指令還 沒有被實作 。
mod_mem_cache:
MCacheSize: 以 KByte 為單位指定快取使用的記憶體空間大小。
MCacheMaxObjectCount: 指定快取物件數目的最大值;預設值是 1009。
MCacheMaxObjectSize: 指定最大可快取物件的大小,單位是 Byte;預設值是10000 (Bytes)。
MCacheMinObjectSize: 指定最小可快取物件的大小,單位是 Byte;預設值是 0 (Bytes)。

2010年6月21日 星期一

RewriteRule flag list

RewriteRule Option
Significance
Description
I
Ignore case
The regular expression of the RewriteRule and any corresponding RewriteCond directives is performed using case-insensitive matching.(不分大小寫)
F
Forbidden(被禁止)
In case the RewriteRule regular expression matches, the web server returns a 404 Not Found response, regardless of the format string (second parameter of RewriteRule) specified. Read Chapter 4 for more details about the HTTP status codes.
L
Last rule
If a match is found, stop processing further rules.
N
Next iteration
Restarts processing the set of rules from the beginning, but using the current rewritten URL. The number of restarts is limited by the value specified with the RepeatLimit directive.
NS
Next iteration of the same rule
Restarts processing the rule, using the rewritten URL. The number of restarts is limited by the value specified with the RepeatLimit directive, and is calculated independently of the number of restarts counted for the N directive.
P
Proxy
Immediately passes the rewritten URL to the ISAPI extension that handles proxy requests. The new URL must be a complete URL that includes the protocol, domain name, and so on.
R
Redirect
Sends a 302 redirect status code to the client pointing to the new URL, instead of rewriting the URL. This is always the last rule, even if the L flag is not specified.
RP
Permanent redirect
The same as R, except the 301 status code is used instead.
U
Unmangle log
Log the new URL as it was the originally requested URL.
O
Normalize
Normalize the URL before processing by removing illegal characters, and so on, and also deletes the query string.
CL
Lowercase
Changes the rewritten URL to lowercase.
CU
Uppercase
Changes the rewritten URL to uppercase.

2010年3月16日 星期二

透過Apache的.htaccess 設置圖片防盜連功能


本站自從搬到美國的新主機後,原本在我自己舊主機設置的防圖片盜連功能就無效了,必須得重新設置防盜連的設定。


對租用網站主機空間的用戶而言,透過Apache的.htaccess來設置防盜連功能(anti hotlink),是最方便的。


新的設定方式如下:

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^http://yblog.org/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://yblog.org$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.yblog.org/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.yblog.org$ [NC]
RewriteRule .*\.(jpg|gif|png|bmp|rar|zip|exe)$ /content/no_hotlink.jpeg [R,NC]


如果你想在自己的網站主機上也使用這樣的防盜連功能,生成一個.htaccess文件放到你欲限制的目錄(根目錄最好避免,在根目錄使用的.htaccess建議用作其它用途,欲限制的目錄下才放本文設定的防盜連方式)。在Windows平台上如果發現自己無法產生.htaccess文件,可以用記事本或其它的文字編輯軟體,另存新檔時,檔名選擇.htaccess即可。


RewriteCond可指定從哪些域名來連線是許可的。
RewriteRule則指定哪些附檔名類型不能被盜連(hotlink),後面可以指定連結到某個錯誤訊息頁面,或者是一張圖片。


如果RewriteRule這一行設定成RewriteRule \.(jpg|jpeg|gif|png|bmp|rar|zip|exe)$ - [F],則表示盜連的人,會看到403錯誤訊息,顯示禁止存取(403 Forbidden)。

如果網站上有 Flash 呼叫外部圖片,要再加上以下這行,不然 FireFox 會誤判。
RewriteCond %{HTTP_REFERER} !^$     [NC]

2010年3月4日 星期四

apache max-age 在 .htaccess

Add an Expires or a Cache-Control Header
Configure ETags
這是 Client Caching 技巧之一
header["Cache-Control"] = "max-age=600",就是 Content 在 600 秒內都是 valid 的.


至於如果最前面的 web server 是 apache 的話,還有一招是在 public/stylesheets 和 public/javascripts 下放置一個有以下內容的 .htaccess 。

    Header add Cache-Control "max-age=86400"

解釋很好~http://blog.xdite.net/?p=1045
1. max-age
2. etag
3. last_modified。

apache 壓力測試結果.

無法查看此摘要。請 按這裡查看文章。

2010年3月1日 星期一

Shell Script To Auto Restart Apache HTTPD

Cron Setup

*/5 * * * * /path/to/script.sh >/dev/null 2>&1



#!/bin/bash
# Apache Process Monitor
# Restart Apache Web Server When It Goes Down
# -------------------------------------------------------------------------
# Copyright (c) 2003 nixCraft project
# This script is licensed under GNU GPL version 2.0 or above
# -------------------------------------------------------------------------
# This script is part of nixCraft shell script collection (NSSC)
# Visit http://bash.cyberciti.biz/ for more information.
# -------------------------------------------------------------------------
# RHEL / CentOS / Fedora Linux restart command
RESTART="/sbin/service httpd restart"

# uncomment if you are using Debian / Ubuntu Linux
#RESTART="/etc/init.d/apache2 restart"

#path to pgrep command
PGREP="/usr/bin/pgrep"

# Httpd daemon name,
# Under RHEL/CentOS/Fedora it is httpd
# Under Debian 4.x it is apache2
HTTPD="httpd"

# find httpd pid
$PGREP ${HTTPD}

if [ $? -ne 0 ] # if apache not running
then
# restart apache
$RESTART
fi


Cron 一行解決.
*/5 * * * * pgrep httpd || service httpd restart >/dev/null 2>&1

2009年5月22日 星期五

Mod_Rewrite 後造成 圖片, css , javascript 連結錯誤[解決方案]

連結

The relative paths are broken because they are relative to the URL in the browser's address bar. For example, if you had a URL of /index.php?page=abc and a relative URL of images/image-one.jpg, the browser would look for the file at /images/image-one.jpg. However, if you use mod_rewrite to change the URL to /pages/abc.html, the browser will now look for the image at /pages/images/image-one.jpg and it won't find it.

To stop this you have a few options:

1. Don't use /. If you don't use slashes (eg. /page-abc.html), the path will be at the same depth and relative URLs won't break.

2. Use absolute paths (everything after the domain name), eg.
Code:
<img src="/images/image-one.jpg" alt="An image of a one">

You would need to edit all the links in your pages.

If you want to be able to move your script and are using a server-side language, you can use a variable or constant so you will only have to change one line. For example in PHP, you would place a constant definition in you global include/configuration file, like this:
Code:
define('MOD_REWRITE_BASE_PATH', '/');

And use it in when outputting your the links
Code:
<a href="<?php echo MOD_REWRITE_BASE_PATH; ?>images/image-one.jpg">foo</a>

If you move the files, you only have to change the value of MOD_REWRITE_BASE_PATH and all the paths will change.

3. There is also a possibility of a mod_reite "hack" to get it to work. In this case, it would be
Code:
RewriteRule ^.+(/images/.+)$ $1 [L]

4. Add a <base>, eg.
Code:
<base href="http://www.domain.com/">



Edit: Added <base>.

mod_rewrite中的正則

文本
. 任意一個單字符
[chars] 字符類: "chars"中的任意一個字符
[^chars] 字符類: 不在"chars"中的字符
text1|text2 選擇: text1 或 text2

量詞
? 前面的字符出現 0 或 1 次
* 前面的字符出現 0 或 N 次(N > 0)
+ 前面的字符出現 1 或 N 次(N > 1)

分組
(text) text 組
(常用於設置一個選擇的邊界,或用於生成後引用:
在RewriteRule中可以用 $N 引用第N個分組)

錨
^ 錨定到行首
$ 錨定到行尾

轉義
\c 對給定的字符c進行轉義
(比如對".[]()"進行轉義,等等)

18 Nov 2007, 16:40下午
Apache: Apache mod_rewrite rewrite 重定向
by 曹宇偉

寫評論
Apache URL重定向指南

Apache URL重定向指南

mod_rewrite入門
Apache mod_rewrite模塊是一個處理URL而又極為複雜的模塊,使用mod_rewrite你可處理所有和URL有關的問題,你所付出的就是花時間去瞭解mod_rewrite的複雜架構,一般初學者都很難實時理解mod_rewrite的用法,有時Apache專家也要mod_rewrite來發展 Apache的新功能。

換句話說,當你成功使用mod_rewrite做到你期望的東西,就不要試圖再接觸mod_rewrite了,因為mod_rewrite的功能實在過於強大。本章的例子會介紹幾個成功的例子給你摸索,不像FAQ形式般把你的問題解答。

實用解決方法
這裡還有很多未被發掘的解決方法,請大家耐心地學習如何使用mod_rewrite。

注意: 由於各人的服務器的配置都有所不同,你可能要更改設定來測試以下例子,例如使用mod_alias和mod_userdir時要加上[PT],或者使用.htaccess來重定向而非主設定文件等,請儘量理解各例子如何運作,不要生吞活剝地背誦。


URL規劃
正規URL
描述:

在某些網頁服務器中,一項資源可能會有數個URL,通常都會公佈一正規URL(即真正發放的URL),其它URL都會被視為快捷方式或只供內部使用等,無論用戶在使用快捷方式或正規URL,用戶最後所重定向到的URL必需為正規。

方法:

我們可將所有非正規的URL重定向至正規的URL中,以下例子把非正規的「/~user」換成正規的「/u/user」,並且加上「/」號結尾。.

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


正規主機名稱
描述:

(省略)

方法:

RewriteCond %{HTTP_HOST} !^fully\.qualified\.domain\.name [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{SERVER_PORT} !^80$
RewriteRule ^/(.*) http://fully.qualified.domain.name:%{SERVER_PORT}/$1 [L,R]
RewriteCond %{HTTP_HOST} !^fully\.qualified\.domain\.name [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^/(.*) http://fully.qualified.domain.name/$1 [L,R]


DocumentRoot被移動
描述:

URL的「/」通常都會映像到DocumentRoot上,但DocumentRoot有時並非重始就限定在某個目錄上,它可能只是一個或多個目錄的對照而矣。例如我們的內聯網址為/e/www/ (WWW的主目錄)和/e/sww/ (內聯網的主目錄)等等,因為所有的網頁資料都放在/e/www/目錄內,我們要確定所有內嵌的圖像都能正確顯示。

方法:

我們只要把「/」重定向至「/e/www/」,用mod_rewrite來解決比用mod_alias來解決更為簡潔,因為URL別名只會比較 URL的前部分,但重定向因可能涉及另一台服務器而需要不同的前綴部分(前綴部分已受DocumentRoot限制),所以mod_rewrite是最好的解決方法::

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


結尾斜線問題
描述:

每個網主都曾受到結尾斜線問題的折磨,若在URL中沒有結尾斜線,服務器就會認為URL無效並返回錯誤,因為服務器會根據/~quux/foo去尋找foo這個檔案,而非顯示這個目錄。其實很多時候,這問題應留待用戶自己加「/」去解決,但有時你也可以完成步驟。例如你做了多次URL重定向,而目的地為一個CGI程序。

方法:

最直觀的方法就是令Apache自動加上「/」,使用外部重定向令瀏覽器能正確找到檔案,若我們只做內部重定向,就只能正確顯示目錄頁,在這目錄頁的圖像文件會因相對URL的問題而找不到。例如我們請求/~quux/foo/index.html的image.gif時,重定向後會變成/~quux /image.gif。

所以我們應使用以下方法:

RewriteEngine on
RewriteBase /~quux/
RewriteRule ^foo$ foo/ [R]


這方法也適用於.htaccess文件在各目錄內設定,但這設定會覆蓋原先主配置文件。

RewriteEngine on
RewriteBase /~quux/
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+[^/])$ $1/ [R]


利用均一的URL版面規劃網絡群組
描述:

所有的網頁服務器都有相同的URL版面,即無論用戶向哪個主機發出請求URL,用戶都會接收到相同的網頁,使URL獨立於服務器本身。我們的目的在於如何在Apache服務器不能響應時,都能有一個常規(而又獨立於服務器運作)的網頁傳送給用戶,設立網絡群組可將這網頁送至遠程。

方法:

首先,服務器需要一外部文件把網站的用戶、用戶組及其它資料存儲,這文件的格式如下

user1 server_of_user1
user2 server_of_user2
: :
把以上資料存入map.xxx-to-host。然後指示服務器把URL重定向,由

/u/user/anypath
/g/group/anypath
/e/entity/anypath
至

http://physical-host/u/user/anypath
http://physical-host/g/group/anypath
http://physical-host/e/entity/anypath
當服務器接收到不正確的URL時,服務器會跟隨以下指示把URL映像到特定的檔案(若URL並沒有相對應的記錄,就會重定向至 server0 上):

RewriteEngine on

RewriteMap user-to-host txt:/path/to/map.user-to-host
RewriteMap group-to-host txt:/path/to/map.group-to-host
RewriteMap entity-to-host txt:/path/to/map.entity-to-host

RewriteRule ^/u/([^/]+)/?(.*) http://${user-to-host:$1|server0}/u/$1/$2
RewriteRule ^/g/([^/]+)/?(.*) http://${group-to-host:$1|server0}/g/$1/$2
RewriteRule ^/e/([^/]+)/?(.*) http://${entity-to-host:$1|server0}/e/$1/$2

RewriteRule ^/([uge])/([^/]+)/?$ /$1/$2/.www/
RewriteRule ^/([uge])/([^/]+)/([^.]+.+) /$1/$2/.www/$3\


把主目錄移到新的網頁服務器
描述:

有很多網主都有以下問題:在升級時把所有用戶主目錄由舊的服務器移到新的服務器上。

方法:

使用mod_rewrite可以簡單地解決這問題,把所有/~user/anypathURL重定向至http://newserver/~user/anypath。

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


結構化用戶主目錄
描述:

擁有大量用戶的主機通常都會把用戶目錄規劃好,將這些目錄歸入一個父目錄中,然後再將用戶的第一個字母作該用戶的父目錄,例如/~foo /anypath將會是/home/f/foo/.www/anypath,而/~bar/anypath就是/home/b/bar/.www /anypath。

方法:

按以下指令將URL直接對映到檔案系統中。

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


重新組織檔案系統
描述:

這是一個麻煩的例子:在不用更動現有目錄結構下,使用RewriteRules來顯示整個目錄結構。背景:net.sw是一個裝滿Unix免費軟件的資料夾,並以下列結構存儲:

drwxrwxr-x 2 netsw users 512 Aug 3 18:39 Audio/
drwxrwxr-x 2 netsw users 512 Jul 9 14:37 Benchmark/
drwxrwxr-x 12 netsw users 512 Jul 9 00:34 Crypto/
drwxrwxr-x 5 netsw users 512 Jul 9 00:41 Database/
drwxrwxr-x 4 netsw users 512 Jul 30 19:25 Dicts/
drwxrwxr-x 10 netsw users 512 Jul 9 01:54 Graphic/
drwxrwxr-x 5 netsw users 512 Jul 9 01:58 Hackers/
drwxrwxr-x 8 netsw users 512 Jul 9 03:19 InfoSys/
drwxrwxr-x 3 netsw users 512 Jul 9 03:21 Math/
drwxrwxr-x 3 netsw users 512 Jul 9 03:24 Misc/
drwxrwxr-x 9 netsw users 512 Aug 1 16:33 Network/
drwxrwxr-x 2 netsw users 512 Jul 9 05:53 Office/
drwxrwxr-x 7 netsw users 512 Jul 9 09:24 SoftEng/
drwxrwxr-x 7 netsw users 512 Jul 9 12:17 System/
drwxrwxr-x 12 netsw users 512 Aug 3 20:15 Typesetting/
drwxrwxr-x 10 netsw users 512 Jul 9 14:08 X11/
我們打算把這個資料夾公開,而且希望直接地顯示這資料夾的目錄結構,但是我們又不想更改現有目錄架構來遷就,加上我們打算開放給FTP,所以不想加入任何網頁或CGI程序到這個資料夾中。

方法:

本方法分為兩部分:第一部份是編寫一系列的CGI程序來顯示目錄結構,這例子會把CGI和剛才的資料夾放進/e/netsw/.www/:

-rw-r–r– 1 netsw users 1318 Aug 1 18:10 .wwwacl
drwxr-xr-x 18 netsw users 512 Aug 5 15:51 DATA/
-rw-rw-rw- 1 netsw users 372982 Aug 5 16:35 LOGFILE
-rw-r–r– 1 netsw users 659 Aug 4 09:27 TODO
-rw-r–r– 1 netsw users 5697 Aug 1 18:01 netsw-about.html
-rwxr-xr-x 1 netsw users 579 Aug 2 10:33 netsw-access.pl
-rwxr-xr-x 1 netsw users 1532 Aug 1 17:35 netsw-changes.cgi
-rwxr-xr-x 1 netsw users 2866 Aug 5 14:49 netsw-home.cgi
drwxr-xr-x 2 netsw users 512 Jul 8 23:47 netsw-img/
-rwxr-xr-x 1 netsw users 24050 Aug 5 15:49 netsw-lsdir.cgi
-rwxr-xr-x 1 netsw users 1589 Aug 3 18:43 netsw-search.cgi
-rwxr-xr-x 1 netsw users 1885 Aug 1 17:41 netsw-tree.cgi
-rw-r–r– 1 netsw users 234 Jul 30 16:35 netsw-unlimit.lst
DATA/子目錄就是剛才的資料夾,net.sw內的軟件會經rdist程序來自動更新。第二部份將這資料夾和新建立的CGI、網頁配合,我們想將 DATA/穩藏起來,而在用戶請求不同URL時執行正確的CGI程序來顯示。先將/net.sw/這URL重定向至/e/netsw:

RewriteRule ^net.sw$ net.sw/ [R]
RewriteRule ^net.sw/(.*)$ e/netsw/$1


第一條規則純粹補加URL結尾的「/」號,而第二條規則就是把URL重定向。之後將下列配置存入/e/netsw/.www/.wwwacl:

Options ExecCGI FollowSymLinks Includes MultiViews

RewriteEngine on

# we are reached via /net.sw/ prefix
RewriteBase /net.sw/

# first we rewrite the root dir to
# the handling cgi script
RewriteRule ^$ netsw-home.cgi [L]
RewriteRule ^index\.html$ netsw-home.cgi [L]

# strip out the subdirs when
# the browser requests us from perdir pages
RewriteRule ^.+/(netsw-[^/]+/.+)$ $1 [L]

# and now break the rewriting for local files
RewriteRule ^netsw-home\.cgi.* - [L]
RewriteRule ^netsw-changes\.cgi.* - [L]
RewriteRule ^netsw-search\.cgi.* - [L]
RewriteRule ^netsw-tree\.cgi$ - [L]
RewriteRule ^netsw-about\.html$ - [L]
RewriteRule ^netsw-img/.*$ - [L]

# anything else is a subdir which gets handled
# by another cgi script
RewriteRule !^netsw-lsdir\.cgi.* - [C]
RewriteRule (.*) netsw-lsdir.cgi/$1


提示:

1. 留意第四部份的L(last)旗標及代表不用更改的(』-')符號

2. 留意最後部份第一條規則的 ! (not)字符,及 C (chain) 鏈接符

3. 留意最後一條規則代表全部更新的語法

以Apache的mod_imap取代NCSA的imagemap
描述:

很多人都想順利地把舊的NCSA服務器遷至新的Apache服務器,所以我們都想將舊的NCSA imagemap順利轉換到Apache的mod_imap,問題是imagemap已被很多超級鏈接連繫著,但舊的imagemap是存儲在/cgi- bin/imagemap/path/to/page.map,而在Apache卻是放在/path/to/page.map。

方法:

我們只要將「/cgi-bin/」移除便可:

RewriteEngine on
RewriteRule ^/cgi-bin/imagemap(.*) $1 [PT]


在多個目錄下搜尋網頁
描述:

MultiViews亦不能指示Apache在多個目錄裡搜尋網頁。

方法:

請參看以下指令。

RewriteEngine on

# first try to find it in custom/…
# …and if found stop and be happy:
RewriteCond /your/docroot/dir1/%{REQUEST_FILENAME} -f
RewriteRule ^(.+) /your/docroot/dir1/$1 [L]

# second try to find it in pub/…
# …and if found stop and be happy:
RewriteCond /your/docroot/dir2/%{REQUEST_FILENAME} -f
RewriteRule ^(.+) /your/docroot/dir2/$1 [L]

# else go on for other Alias or ScriptAlias directives,
# etc.
RewriteRule ^(.+) - [PT]


跟據URL設定環境變量
描述:

在頁面間傳遞訊息可以用CGI程序完成,但你卻不想用CGI而用URL來傳遞。

方法:

以下指令將變量及其值抽出URL外,然後記入自設的環境變量中,該變量可由XSSI或CGI存取。例如把/foo/S=java/bar/轉換為/foo/bar/,然後把「java」寫入環境變量「STATUS」。

RewriteEngine on
RewriteRule ^(.*)/S=([^/]+)/(.*) $1/$3 [E=STATUS:$2]


虛擬用戶主機
描述:

你只想根據DNS記錄將www.username.host.domain.com的請求直接對映到檔案系統,放棄使用Apache的虛擬主機功能。

方法:

只有HTTP/1.1請求才可用以下方法做到,我們可根據HTTP Header把http://www.username.host.com/anypath重定向到/home/username/anypath:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.[^.]+\.host\.com$
RewriteRule ^(.+) %{HTTP_HOST}$1 [C]
RewriteRule ^www\.([^.]+)\.host\.com(.*) /home/$1$2


將遠程請求重定向至另一個用戶主目錄
描述:

當用者的主機不屬於自己的網域ourdomain.com時,就將請求重定向至www.somewhere.com</CODE。< dd>

方法:

請參看以下指令:

RewriteEngine on
RewriteCond %{REMOTE_HOST} !^.+\.ourdomain\.com$
RewriteRule ^(/~.+) http://www.somewhere.com/$1 [R,L]


將失敗的網頁請求重定向至另一部網頁服務器
描述:

這是一般常見的疑問,最直觀的方法就是用ErrorDocument加上CGI-scripts更改目標URL,但我們亦可使用mod_rewrite來實行(這方法的效率卻比CGI程序更低)。

方法:

再一次留意CGI會是更有效率的解決方法,而mod_rewrite的好處在於更安全及易設置:

RewriteEngine on
RewriteCond /your/docroot/%{REQUEST_FILENAME} !-f
RewriteRule ^(.+) http://webserverB.dom/$1


以上例子會限制所有網頁在DocumentRoot才能成功,我們可加多一點指令來改善:

RewriteEngine on
RewriteCond %{REQUEST_URI} !-U
RewriteRule ^(.+) http://webserverB.dom/$1


這例子使用了mod_rewrite預計URL改動的功能,所有URL都可以安全地重定向至新的目錄,但在速度慢的主機上不宜使用這方法,因為採用本例會拖慢服務器工作,當然你可以在高速CPU主機上使用。

更廣泛的URL重定向
描述:

我們想重定向有控制字符的URL,例如」url#anchor」等,通常Apache會用uri_escape()函數來隔除這些控制字符,因此你不可以直接用mod_rewrite來重定向這類URL。

方法:

我們要使用一NPH-CGI(NPH = non-parseable headers)程序處理重定向工作,因為NPH-CGI不會隔除控制字符。首先,我們先利用xredirect:

RewriteRule ^xredirect:(.+) /path/to/nph-xredirect.cgi/$1 \
[T=application/x-httpd-cgi,L]


強制性將所有URL加上xredirect,然後將URL導入nph-xredirect.cgi中,程序代碼如下:

#!/path/to/perl
##
## nph-xredirect.cgi — NPH/CGI script for extended redirects
## Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved.
##

$| = 1;
$url = $ENV{』PATH_INFO'};

print 「HTTP/1.0 302 Moved Temporarily\n」;
print 「Server: $ENV{』SERVER_SOFTWARE'}\n」;
print 「Location: $url\n」;
print 「Content-type: text/html\n」;
print 「\n」;
print 「<html>\n」;
print 「<head>\n」;
print 「<title>302 Moved Temporarily (EXTENDED)</title>\n」;
print 「</head>\n」;
print 「<body>\n」;
print 「<h1>Moved Temporarily (EXTENDED)</h1>\n」;
print 「The document has moved <a HREF=\」$url\」>here</a>.<p>\n」;
print 「</body>\n」;
print 「</html>\n」;

##EOF##


這樣可將所有能或不能直接用mod_rewrite來重定向的URL,經CGI來完成了。例如你可將某URL重定向至新聞服務器

RewriteRule ^anyurl xredirect:news:newsgroup


注意:你不需在每條規則後加上[R]或[R,L]。

多樣化資料夾存取
描述:

若你曾瀏覽http://www.perl.com/CPAN (CPAN = Comprehensive Perl Archive Network),它會把你重定向至其中一個最近你主機地區的FTP服務器,事實上這應該叫多樣化FTP存取。CPAN用CGI來實行這服務,這次我們用mod_rewrite。

<STRONG方法:< strong>

由mod_rewrite 3.0.0開始可使用「ftp:」重定向至FTP服務器,用戶主機的地區可依URL的頂層域名來決定,而頂層域名及FTP服務器位置的對照就存入某檔案中。

RewriteEngine on
RewriteMap multiplex txt:/path/to/map.cxan
RewriteRule ^/CxAN/(.*) %{REMOTE_HOST}::$1 [C]
RewriteRule ^.+\.([a-zA-Z]+)::(.*)$ ${multiplex:$1|ftp.default.dom}$2 [R,L]


##
## map.cxan — Multiplexing Map for CxAN
##

de ftp://ftp.cxan.de/CxAN/
uk ftp://ftp.cxan.uk/CxAN/
com ftp://ftp.cxan.com/CxAN/
:
##EOF##


在某段時間執行不同的重定向
描述n:

很多網主仍用CGI隨著不同時間將URL重定向至不同的網頁。

方法:

mod_rewrite設有很多以TIME_xxx開始的環境變量,將這些時間環境變量進行字符串比較可決定重定向至哪個網頁:

RewriteEngine on
RewriteCond %{TIME_HOUR}%{TIME_MIN} >0700
RewriteCond %{TIME_HOUR}%{TIME_MIN} <1900
RewriteRule ^foo\.html$ foo.day.html
RewriteRule ^foo\.html$ foo.night.html


在07:00-19:00就顯示foo.day.html,其餘時間則顯示foo.html

保留舊有文件的URL
描述:

更改文件的擴展名後,如何讓舊的URL能對映到這新的文件。

方法:

把舊的URL用mod_rewrite重定向至新的文件,若有正確的新文件就對映到這文件,沒有的話便對映到原有文件。

# backward compatibility ruleset for
# rewriting document.html to document.phtml
# when and only when document.phtml exists
# but no longer document.html
RewriteEngine on
RewriteBase /~quux/
# parse out basename, but remember the fact
RewriteRule ^(.*)\.html$ $1 [C,E=WasHTML:yes]
# rewrite to document.phtml if exists
RewriteCond %{REQUEST_FILENAME}.phtml -f
RewriteRule ^(.*)$ $1.phtml [S=1]
# else reverse the previous basename cutout
RewriteCond %{ENV:WasHTML} ^yes$
RewriteRule ^(.*)$ $1.html


內容控制
由舊的檔名轉到新的文件名 (檔案系統)
描述:

假設我們將bar.html改名為foo.html,而我們又想保留舊有的URL,甚至不想給用戶新的URL去連至這新檔案。

方法:

將舊的檔案對映到新的檔案:

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


由舊的檔名轉到新的檔名 (URL)
描述:

和剛才的例子一樣,我們把bar.html改名為foo.html,但這次我們想直接將用戶的網頁重定向至新的文件,即瀏覽器的URL位置有所改變。

方法:

強制性將URL對映到新的URL:

RewriteEngine on
RewriteBase /~quux/
RewriteRule ^foo\.html$ bar.html [R]


由瀏覽器種類控制內容
描述:

一個出色的網頁應能支持各種瀏覽器,例如我們要把完整版網頁傳送至Netscape,但就要傳送文字版至Lynx。

方法:

由於瀏覽器沒有提供Apache格式的瀏覽器種類資料,所以我們不可使用內文轉換(mod_negotiation),我們必需用「User- Agent」決定瀏覽器種類。例如User-Agent為「Mozilla/3」就把「foo.html」重定向至「foo.NS.html」;若瀏覽器為「Lynx」或「Mozilla」就重定向至foo.20.html,其它種類的瀏覽器則導向至foo.32.html:

RewriteCond %{HTTP_USER_AGENT} ^Mozilla/3.*
RewriteRule ^foo\.html$ foo.NS.html [L]

RewriteCond %{HTTP_USER_AGENT} ^Lynx/.* [OR]
RewriteCond %{HTTP_USER_AGENT} ^Mozilla/[12].*
RewriteRule ^foo\.html$ foo.20.html [L]

RewriteRule ^foo\.html$ foo.32.html [L]


動態本地檔案更新(經鏡像網站)
描述:

你想將某個主機的網頁連結到你的網頁目錄,若被連結的是FTP服務器,你可用mirror程序將最新的檔案移到自己的主機上,我們可用 webcopy經網頁服務器HTTP把檔案下載,但這方法有一壞處:只有在執行webcopy時才能更新檔案。更好的辦法就是在發出請求時立刻找尋最新的檔案來源,然後實時下載到自己主機中。

方法:

利用Proxy Throughput(flag [P])把遠程網頁甚至整個網站建立一直接對照。

RewriteEngine on
RewriteBase /~quux/
RewriteRule ^hotsheet/(.*)$ http://www.tstimpreso.com/hotsheet/$1 [P]


RewriteEngine on
RewriteBase /~quux/
RewriteRule ^usa-news\.html$ http://www.quux-corp.com/news/index.html [P]


動態鏡像檔案更新(經本主機)
描述:

(省略)

方法:

RewriteEngine on
RewriteCond /mirror/of/remotesite/$1 -U
RewriteRule ^http://www\.remotesite\.com/(.*)$ /mirror/of/remotesite/$1


由內部網絡更新檔案
描述:

為了安全起見,我們建立了兩個網頁服務器,第一個是公開的(www.quux-corp.dom),第二個則是內部使用,受防火牆所保護,一切資料及網站維護都經這個服務器進行,現在我們想令外部服務器能存取穿過防火牆,獲取內部服務器已最新的檔案。

方法:

我們只容許外部服務器從內部獲取資料,一切直接獲取的請求都受防火牆拒絕,先在防火牆設定:

ALLOW Host www.quux-corp.dom Port >1024 –> Host www2.quux-corp.dom Port 80
DENY Host * Port * –> Host www2.quux-corp.dom Port 80


把以上的字句譯成設置防火牆的語法,然後在mod_rewrite透過proxy throughput獲取最新資料:

RewriteRule ^/~([^/]+)/?(.*) /home/$1/.www/$2
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/home/([^/]+)/.www/?(.*) http://www2.quux-corp.dom/~$1/pub/$2 [P]


平衡服務器負荷
描述:

我們想將www[0-5].foo.com這六部服務器的工作量平均分配。

方法:

當然你會有很多方法達成,一般都會使用DNS,介紹完DNS後再會討論mod_rewrite如何實行。

1. DNS循環機制

最簡單的方法就是使用BIND的循環機制,e.g.

www0 IN A 1.2.3.1
www1 IN A 1.2.3.2
www2 IN A 1.2.3.3
www3 IN A 1.2.3.4
www4 IN A 1.2.3.5
www5 IN A 1.2.3.6


然後加上以下記錄:

www IN CNAME www0.foo.com.
IN CNAME www1.foo.com.
IN CNAME www2.foo.com.
IN CNAME www3.foo.com.
IN CNAME www4.foo.com.
IN CNAME www5.foo.com.
IN CNAME www6.foo.com.


在DNS層面上這種設定當然是錯的,但我們正好使用了BIND的循環機制,BIND接收到www.foo.com的解析請求,然後BIND就會循環地解析作www0-www6,這樣就能將用戶分配到不同的服務器上,但請記得這不是一個完美的方案,因為其它的域名服務器會快取你服務器的域名解析結果,所以每一次解析到wwwX.foo.com時,都會有很多用戶同時被派往同一部服務器,但整體來說已能平衡各服務器的負荷。

2. DNS平衡負荷

在http://www.stanford.edu/~schemers/docs/lbnamed/lbnamed.html有一個lbnamed程序專責利用域名服務器把用戶請求分發到不同的服務器上,這是一個用Perl 5及其它附助工具寫的複雜DNS工作量分配程序。

3. 代理服務器循環建立機制

我們使用mod_rewrite及其代理服務器網頁記錄(proxy throughput)功能,先在DNS加入www0.foo.com即是www.foo.com的記錄。

www IN CNAME www0.foo.com.


然後將www0.foo.com變為一獨立代理服務器,即是建立一專責代理服務器,然後把請求分流至五部不同的服務器(www1-www5),我們用lb.pl及以下mod_rewrite規則:

RewriteEngine on
RewriteMap lb prg:/path/to/lb.pl
RewriteRule ^/(.+)$ ${lb:$1} [P,L]


lb.pl的程序代碼:

#!/path/to/perl
##
## lb.pl — load balancing script
##

$| = 1;

$name = 「www」; # the hostname base
$first = 1; # the first server (not 0 here, because 0 is myself)
$last = 5; # the last server in the round-robin
$domain = 「foo.dom」; # the domainname

$cnt = 0;
while (<STDIN>) {
$cnt = (($cnt+1) % ($last+1-$first));
$server = sprintf(」%s%d.%s」, $name, $cnt+$first, $domain);
print 「http://$server/$_」;
}

##EOF##


注意,www0.foo.com這服務器的工作量仍然和以前一樣高,但這服務器的工作就只是負責分流,所有SSI、CGI、ePerl請求都由其它服務器執行,所以整體的工作量已經減少了許多。

4. 硬件/TCP循環機制

可Cisco的LocalDirector在TCP/IP網絡層上把用戶請求分流,事實上這種分流程序已刻烙在是電路板上。與硬件有關的解決方法通常都需要大量的金錢,但執行效率就會是最高。

將請求重定向至代理服務器
描述:

(省略)

方法:

##
## apache-rproxy.conf — Apache configuration for Reverse Proxy Usage
##

# server type
ServerType standalone
Port 8000
MinSpareServers 16
StartServers 16
MaxSpareServers 16
MaxClients 16
MaxRequestsPerChild 100

# server operation parameters
KeepAlive on
MaxKeepAliveRequests 100
KeepAliveTimeout 15
Timeout 400
IdentityCheck off
HostnameLookups off

# paths to runtime files
PidFile /path/to/apache-rproxy.pid
LockFile /path/to/apache-rproxy.lock
ErrorLog /path/to/apache-rproxy.elog
CustomLog /path/to/apache-rproxy.dlog 「%{%v/%T}t %h -> %{SERVER}e URL: %U」

# unused paths
ServerRoot /tmp
DocumentRoot /tmp
CacheRoot /tmp
RewriteLog /dev/null
TransferLog /dev/null
TypesConfig /dev/null
AccessConfig /dev/null
ResourceConfig /dev/null

# speed up and secure processing
<Directory />
Options -FollowSymLinks -SymLinksIfOwnerMatch
AllowOverride None
</Directory>

# the status page for monitoring the reverse proxy
<Location /apache-rproxy-status>
SetHandler server-status
</Location>

# enable the URL rewriting engine
RewriteEngine on
RewriteLogLevel 0

# define a rewriting map with value-lists where
# mod_rewrite randomly chooses a particular value
RewriteMap server rnd:/path/to/apache-rproxy.conf-servers

# make sure the status page is handled locally
# and make sure no one uses our proxy except ourself
RewriteRule ^/apache-rproxy-status.* - [L]
RewriteRule ^(http|ftp)://.* - [F]

# now choose the possible servers for particular URL types
RewriteRule ^/(.*\.(cgi|shtml))$ to://${server:dynamic}/$1 [S=1]
RewriteRule ^/(.*)$ to://${server:static}/$1

# and delegate the generated URL by passing it
# through the proxy module
RewriteRule ^to://([^/]+)/(.*) http://$1/$2 [E=SERVER:$1,P,L]

# and make really sure all other stuff is forbidden
# when it should survive the above rules…
RewriteRule .* - [F]

# enable the Proxy module without caching
ProxyRequests on
NoCache *

# setup URL reverse mapping for redirect reponses
ProxyPassReverse / http://www1.foo.dom/
ProxyPassReverse / http://www2.foo.dom/
ProxyPassReverse / http://www3.foo.dom/
ProxyPassReverse / http://www4.foo.dom/
ProxyPassReverse / http://www5.foo.dom/
ProxyPassReverse / http://www6.foo.dom/


##
## apache-rproxy.conf-servers — Apache/mod_rewrite selection table
##

# list of backend servers which serve static
# pages (HTML files and Images, etc.)
static www1.foo.dom|www2.foo.dom|www3.foo.dom|www4.foo.dom

# list of backend servers which serve dynamically
# generated page (CGI programs or mod_perl scripts)
dynamic www5.foo.dom|www6.foo.dom


建立新的檔案型態及服務
描述:

你可在網上找到大量華麗的CGI程序,但又因這些CGI的艱難用法,很多人都不願意使用,甚至Apache Action Handler的MIME類型亦On the net there are a lot of nifty CGI programs. But their usage is usually boring, so a lot of webmaster don't use them. Even Apache's Action handler feature for MIME-types is only appropriate when the CGI programs don't need special URLs (actually PATH_INFO and QUERY_STRINGS) as their input. First, let us configure a new file type with extension .scgi (for secure CGI) which will be processed by the popular cgiwrap program. The problem here is that for instance we use a Homogeneous URL Layout (see above) a file inside the user homedirs has the URL /u/user/foo/bar.scgi. But cgiwrap needs the URL in the form /~user/foo/bar.scgi/. The following rule solves the problem:

RewriteRule ^/[uge]/([^/]+)/\.www/(.+)\.scgi(.*) …
… /internal/cgi/user/cgiwrap/~$1/$2.scgi$3 [NS,T=application/x-http-cgi]


Or assume we have some more nifty programs: wwwlog (which displays the access.log for a URL subtree and wwwidx (which runs Glimpse on a URL subtree). We have to provide the URL area to these programs so they know on which area they have to act on. But usually this ugly, because they are all the times still requested from that areas, i.e. typically we would run the swwidx program from within /u/user/foo/ via hyperlink to

/internal/cgi/user/swwidx?i=/u/user/foo/
which is ugly. Because we have to hard-code both the location of the area and the location of the CGI inside the hyperlink. When we have to reorganise or area, we spend a lot of time changing the various hyperlinks.

Solution:

The solution here is to provide a special new URL format which automatically leads to the proper CGI invocation. We configure the following:

RewriteRule ^/([uge])/([^/]+)(/?.*)/\* /internal/cgi/user/wwwidx?i=/$1/$2$3/
RewriteRule ^/([uge])/([^/]+)(/?.*):log /internal/cgi/user/wwwlog?f=/$1/$2$3


Now the hyperlink to search at /u/user/foo/ reads only

HREF=」*」
which internally gets automatically transformed to

/internal/cgi/user/wwwidx?i=/u/user/foo/
The same approach leads to an invocation for the access log CGI program when the hyperlink :log gets used.

From Static to Dynamic
Description:

How can we transform a static page foo.html into a dynamic variant foo.cgi in a seemless way, i.e. without notice by the browser/user.

Solution:

We just rewrite the URL to the CGI-script and force the correct MIME-type so it gets really run as a CGI-script. This way a request to /~quux/foo.html internally leads to the invokation of /~quux/foo.cgi.

RewriteEngine on
RewriteBase /~quux/
RewriteRule ^foo\.html$ foo.cgi [T=application/x-httpd-cgi]


On-the-fly Content-Regeneration
Description:

Here comes a really esoteric feature: Dynamically generated but statically served pages, i.e. pages should be delivered as pure static pages (read from the filesystem and just passed through), but they have to be generated dynamically by the webserver if missing. This way you can have CGI-generated pages which are statically served unless one (or a cronjob) removes the static contents. Then the contents gets refreshed.

Solution:

This is done via the following ruleset:

RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^page\.html$ page.cgi [T=application/x-httpd-cgi,L]


Here a request to page.html leads to a internal run of a corresponding page.cgi if page.html is still missing or has filesize null. The trick here is that page.cgi is a usual CGI script which (additionally to its STDOUT) writes its output to the file page.html. Once it was run, the server sends out the data of page.html. When the webmaster wants to force a refresh the contents, he just removes page.html (usually done by a cronjob).

Document With Autorefresh
Description:

Wouldn't it be nice while creating a complex webpage if the webbrowser would automatically refresh the page every time we write a new version from within our editor? Impossible?

Solution:

No! We just combine the MIME multipart feature, the webserver NPH feature and the URL manipulation power of mod_rewrite. First, we establish a new URL feature: Adding just :refresh to any URL causes this to be refreshed every time it gets updated on the filesystem.

RewriteRule ^(/[uge]/[^/]+/?.*):refresh /internal/cgi/apache/nph-refresh?f=$1


Now when we reference the URL

/u/foo/bar/page.html:refresh
this leads to the internal invocation of the URL

/internal/cgi/apache/nph-refresh?f=/u/foo/bar/page.html
The only missing part is the NPH-CGI script. Although one would usually say 「left as an exercise to the reader」 ;-) I will provide this, too.

#!/sw/bin/perl
##
## nph-refresh — NPH/CGI script for auto refreshing pages
## Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved.
##
$| = 1;

# split the QUERY_STRING variable
@pairs = split(/&/, $ENV{』QUERY_STRING'});
foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$name =~ tr/A-Z/a-z/;
$name = 『QS_』 . $name;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(」C」, hex($1))/eg;
eval 「\$$name = \」$value\」";
}
$QS_s = 1 if ($QS_s eq 」);
$QS_n = 3600 if ($QS_n eq 」);
if ($QS_f eq 」) {
print 「HTTP/1.0 200 OK\n」;
print 「Content-type: text/html\n\n」;
print 「&lt;b&gt;ERROR&lt;/b&gt;: No file given\n」;
exit(0);
}
if (! -f $QS_f) {
print 「HTTP/1.0 200 OK\n」;
print 「Content-type: text/html\n\n」;
print 「&lt;b&gt;ERROR&lt;/b&gt;: File $QS_f not found\n」;
exit(0);
}

sub print_http_headers_multipart_begin {
print 「HTTP/1.0 200 OK\n」;
$bound = 「ThisRandomString12345〞;
print 「Content-type: multipart/x-mixed-replace;boundary=$bound\n」;
&print_http_headers_multipart_next;
}

sub print_http_headers_multipart_next {
print 「\n–$bound\n」;
}

sub print_http_headers_multipart_end {
print 「\n–$bound–\n」;
}

sub displayhtml {
local($buffer) = @_;
$len = length($buffer);
print 「Content-type: text/html\n」;
print 「Content-length: $len\n\n」;
print $buffer;
}

sub readfile {
local($file) = @_;
local(*FP, $size, $buffer, $bytes);
($x, $x, $x, $x, $x, $x, $x, $size) = stat($file);
$size = sprintf(」%d」, $size);
open(FP, 「&lt;$file」);
$bytes = sysread(FP, $buffer, $size);
close(FP);
return $buffer;
}

$buffer = &readfile($QS_f);
&print_http_headers_multipart_begin;
&displayhtml($buffer);

sub mystat {
local($file) = $_[0];
local($time);

($x, $x, $x, $x, $x, $x, $x, $x, $x, $mtime) = stat($file);
return $mtime;
}

$mtimeL = &mystat($QS_f);
$mtime = $mtime;
for ($n = 0; $n &lt; $QS_n; $n++) {
while (1) {
$mtime = &mystat($QS_f);
if ($mtime ne $mtimeL) {
$mtimeL = $mtime;
sleep(2);
$buffer = &readfile($QS_f);
&print_http_headers_multipart_next;
&displayhtml($buffer);
sleep(5);
$mtimeL = &mystat($QS_f);
last;
}
sleep($QS_s);
}
}

&print_http_headers_multipart_end;

exit(0);

##EOF##
Mass Virtual Hosting
Description:

The <VirtualHost> feature of Apache is nice and works great when you just have a few dozens virtual hosts. But when you are an ISP and have hundreds of virtual hosts to provide this feature is not the best choice.

Solution:

To provide this feature we map the remote webpage or even the complete remote webarea to our namespace by the use of the Proxy Throughput feature (flag [P]):

##
## vhost.map
##
www.vhost1.dom:80 /path/to/docroot/vhost1
www.vhost2.dom:80 /path/to/docroot/vhost2
:
www.vhostN.dom:80 /path/to/docroot/vhostN


##
## httpd.conf
##
:
# use the canonical hostname on redirects, etc.
UseCanonicalName on

:
# add the virtual host in front of the CLF-format
CustomLog /path/to/access_log 「%{VHOST}e %h %l %u %t \」%r\」 %>s %b」
:

# enable the rewriting engine in the main server
RewriteEngine on

# define two maps: one for fixing the URL and one which defines
# the available virtual hosts with their corresponding
# DocumentRoot.
RewriteMap lowercase int:tolower
RewriteMap vhost txt:/path/to/vhost.map

# Now do the actual virtual host mapping
# via a huge and complicated single rule:
#
# 1. make sure we don't map for common locations
RewriteCond %{REQUEST_URI} !^/commonurl1/.*
RewriteCond %{REQUEST_URI} !^/commonurl2/.*
:
RewriteCond %{REQUEST_URI} !^/commonurlN/.*
#
# 2. make sure we have a Host header, because
# currently our approach only supports
# virtual hosting through this header
RewriteCond %{HTTP_HOST} !^$
#
# 3. lowercase the hostname
RewriteCond ${lowercase:%{HTTP_HOST}|NONE} ^(.+)$
#
# 4. lookup this hostname in vhost.map and
# remember it only when it is a path
# (and not 「NONE」 from above)
RewriteCond ${vhost:%1} ^(/.*)$
#
# 5. finally we can map the URL to its docroot location
# and remember the virtual host for logging puposes
RewriteRule ^/(.*)$ %1/$1 [E=VHOST:${lowercase:%{HTTP_HOST}}]
:


Access Restriction
Blocking of Robots
Description:

How can we block a really annoying robot from retrieving pages of a specific webarea? A /robots.txt file containing entries of the 「Robot Exclusion Protocol」 is typically not enough to get rid of such a robot.

Solution:

We use a ruleset which forbids the URLs of the webarea /~quux/foo/arc/ (perhaps a very deep directory indexed area where the robot traversal would create big server load). We have to make sure that we forbid access only to the particular robot, i.e. just forbidding the host where the robot runs is not enough. This would block users from this host, too. We accomplish this by also matching the User-Agent HTTP header information.

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


Blocked Inline-Images
Description:

Assume we have under http://www.quux-corp.de/~quux/ some pages with inlined GIF graphics. These graphics are nice, so others directly incorporate them via hyperlinks to their pages. We don't like this practice because it adds useless traffic to our server.

Solution:

While we cannot 100% protect the images from inclusion, we can at least restrict the cases where the browser sends a HTTP Referer header.

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


RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !.*/foo-with-gif\.html$
RewriteRule ^inlined-in-foo\.gif$ - [F]


Host Deny
Description:

How can we forbid a list of externally configured hosts from using our server?

Solution:

For Apache >= 1.3b6:

RewriteEngine on
RewriteMap hosts-deny txt:/path/to/hosts.deny
RewriteCond ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND} !=NOT-FOUND [OR]
RewriteCond ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND} !=NOT-FOUND
RewriteRule ^/.* - [F]


For Apache <= 1.3b6:

RewriteEngine on
RewriteMap hosts-deny txt:/path/to/hosts.deny
RewriteRule ^/(.*)$ ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND}/$1
RewriteRule !^NOT-FOUND/.* – [F]
RewriteRule ^NOT-FOUND/(.*)$ ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND}/$1
RewriteRule !^NOT-FOUND/.* – [F]
RewriteRule ^NOT-FOUND/(.*)$ /$1


##
## hosts.deny
##
## ATTENTION! This is a map, not a list, even when we treat it as such.
## mod_rewrite parses it for key/value pairs, so at least a
## dummy value 「-」 must be present for each entry.
##

193.102.180.41 -
bsdti1.sdm.de -
192.76.162.40 -


URL-Restricted Proxy
Description:

How can we restrict the proxy to allow access to a configurable set of internet sites only? The site list is extracted from a prepared bookmarks file.

Solution:

We first have to make sure mod_rewrite is below(!) mod_proxy in the Configuration file when compiling the Apache webserver (or in the AddModule list of httpd.conf in the case of dynamically loaded modules), as it must get called _before_ mod_proxy.

For simplicity, we generate the site list as a textfile map (but see the mod_rewrite documentation for a conversion script to DBM format). A typical Netscape bookmarks file can be converted to a list of sites with a shell script like this:

#!/bin/sh
cat ${1:-~/.netscape/bookmarks.html} |
tr -d 『\015′ | tr 『[A-Z]『 『[a-z]『 | grep href=\」 |
sed -e 『/href=」file:/d;』 -e 『/href=」news:/d;』 \
-e 』s|^.*href=」[^:]*://\([^:/"]*\).*$|\1 OK|;』 \
-e 『/href=」/s|^.*href=」\([^:/"]*\).*$|\1 OK|;』 |
sort -u


We redirect the resulting output into a text file called goodsites.txt. It now looks similar to this:

www.apache.org OK
xml.apache.org OK
jakarta.apache.org OK
perl.apache.org OK
…


We reference this site file within the configuration for the VirtualHost which is responsible for serving as a proxy (often not port 80, but 81, 8080 or 8008).

<VirtualHost *:8008>
…
RewriteEngine On
# Either use the (plaintext) allow list from goodsites.txt
RewriteMap ProxyAllow txt:/usr/local/apache/conf/goodsites.txt
# Or, for faster access, convert it to a DBM database:
#RewriteMap ProxyAllow dbm:/usr/local/apache/conf/goodsites
# Match lowercased hostnames
RewriteMap lowercase int:tolower
# Here we go:
# 1) first lowercase the site name and strip off a :port suffix
RewriteCond ${lowercase:%{HTTP_HOST}} ^([^:]*).*$
# 2) next look it up in the map file.
# 「%1〞 refers to the previous regex.
# If the result is 「OK」, proxy access is granted.
RewriteCond ${ProxyAllow:%1|DENY} !^OK$ [NC]
# 3) Disallow proxy requests if the site was _not_ tagged 「OK」:
RewriteRule ^proxy: - [F]
…
</VirtualHost>


Proxy Deny
Description:

How can we forbid a certain host or even a user of a special host from using the Apache proxy?

Solution:

We first have to make sure mod_rewrite is below(!) mod_proxy in the Configuration file when compiling the Apache webserver. This way it gets called _before_ mod_proxy. Then we configure the following for a host-dependend deny…

RewriteCond %{REMOTE_HOST} ^badhost\.mydomain\.com$
RewriteRule !^http://[^/.]\.mydomain.com.* – [F]


…and this one for a user@host-dependend deny:

RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} ^badguy@badhost\.mydomain\.com$
RewriteRule !^http://[^/.]\.mydomain.com.* – [F]


Special Authentication Variant
Description:

Sometimes a very special authentication is needed, for instance a authentication which checks for a set of explicitly configured users. Only these should receive access and without explicit prompting (which would occur when using the Basic Auth via mod_access).

Solution:

We use a list of rewrite conditions to exclude all except our friends:

RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend1@client1.quux-corp\.com$
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend2@client2.quux-corp\.com$
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend3@client3.quux-corp\.com$
RewriteRule ^/~quux/only-for-friends/ - [F]


Referer-based Deflector
Description:

How can we program a flexible URL Deflector which acts on the 「Referer」 HTTP header and can be configured with as many referring pages as we like?

Solution:

Use the following really tricky ruleset…

RewriteMap deflector txt:/path/to/deflector.map

RewriteCond %{HTTP_REFERER} !=」"
RewriteCond ${deflector:%{HTTP_REFERER}} ^-$
RewriteRule ^.* %{HTTP_REFERER} [R,L]

RewriteCond %{HTTP_REFERER} !=」"
RewriteCond ${deflector:%{HTTP_REFERER}|NOT-FOUND} !=NOT-FOUND
RewriteRule ^.* ${deflector:%{HTTP_REFERER}} [R,L]


… in conjunction with a corresponding rewrite map:

##
## deflector.map
##

http://www.badguys.com/bad/index.html -
http://www.badguys.com/bad/index2.html -
http://www.badguys.com/bad/index3.html http://somewhere.com/


This automatically redirects the request back to the referring page (when 「-」 is used as the value in the map) or to a specific URL (when an URL is specified in the map as the second argument).

Other
External Rewriting Engine
Description:

A FAQ: How can we solve the FOO/BAR/QUUX/etc. problem? There seems no solution by the use of mod_rewrite…

Solution:

Use an external rewrite map, i.e. a program which acts like a rewrite map. It is run once on startup of Apache receives the requested URLs on STDIN and has to put the resulting (usually rewritten) URL on STDOUT (same order!).

RewriteEngine on
RewriteMap quux-map prg:/path/to/map.quux.pl
RewriteRule ^/~quux/(.*)$ /~quux/${quux-map:$1}


#!/path/to/perl

# disable buffered I/O which would lead
# to deadloops for the Apache server
$| = 1;

# read URLs one per line from stdin and
# generate substitution URL on stdout
while (<>) {
s|^foo/|bar/|;
print $_;
}


This is a demonstration-only example and just rewrites all URLs /~quux/foo/… to /~quux/bar/…. Actually you can program whatever you like. But notice that while such maps can be used also by an average user, only the system administrator can define it.