開源碼社群中的地理位置管控模組mod_maxminddb,讓使用者除了利用傳統的IP管控機制外,還可導入以地理位置為基礎的存取控制。本文將以Apache網站伺服器為例,動手實作為其加上以地理位置來限定連線的功能。
隨著網站服務日益普及,其所面臨的資安威脅也愈加嚴峻。在現今網際網路環境中,網站時時都會面臨來自世界各地的惡意攻擊行為,例如自動化弱點掃描、針對帳號密碼的暴力攻擊等等。
一般而言,當網站管理者偵測到此類異常活動時,通常會透過防火牆或其他資安設備,針對可疑來源IP進行封鎖,以降低潛在風險。然而,在現今的網路環境中,僅單純依靠以IP為基礎的防護策略,往往難以全面應對日益複雜的攻擊手法,例如攻擊者可利用代理伺服器或使用VPN等方式來隨機變換IP。若單純僅依靠以來源IP封鎖的方式,將無法真正有效地封鎖來源IP。
本文將介紹一套開源碼社群中有名的地理位置管控模組mod_maxminddb,其官方網址是「https://github.com/maxmind/mod_maxminddb?tab=readme-ov-file」,讓使用者除了利用傳統的IP管控機制外,還導入了以地理位置(如僅允許某個特定國家或地區的連線)為基礎的存取控制(Geo-based Access Control),並以著名的Apache網站伺服器為例,為其加上以地理位置來限定連線的功能。而本次所使用的作業系統為CentOS Stream 9。
什麼是mod_maxminddb
mod_maxminddb是一個Apache的模組程式,主要功能是將IP位址(通常是網站的連線來源IP位址)轉換為地理位置,例如將168.95.1.1轉換成國別代碼如TW。而後再藉由網站的存取控制機制,針對轉換後的地理位置資訊進行相關規則管控,例如設定僅允許來自台灣的來源能進行連線。其運作流程,簡單說明如下:
1. 使用者瀏覽網站。
2. Apache網站伺服器接收到使用者的要求(Request)後,其mod_maxminddb模組會取得使用者的來源IP,並藉由查詢地理資料庫(本文使用GeoLite的地理資料庫)來取得該來源IP所對應的地理位置,然後將該資料儲存於變數中。
3. Apache網站伺服器可針對該變數設定相關管控規則,以決定該連線是否可存取。
安裝mod_maxminddb模組
在了解相關運作後,接著就來安裝mod_maxminddb模組。在安裝之前,必須先安裝地理資料庫。首先執行以下的指令,安裝用來讀取地理資料庫格式(格式為mndb)的相關程式庫:
dnf install libmaxminddb dnf install libmaxminddb-devel
接著,下載相關的地理資料庫。相關資料庫目前是由maxmind公司(https://www.maxmind.com/)所維護,提供付費的完整版本或免費的精簡(GeoLite)版本,在本文中使用的版本為精簡版。不管是完整或精簡版本,均須先註冊為該公司的會員,才可以下載地理資料庫,因此先連線至網址「https://www.maxmind.com/en/create-account」進行註冊。
註冊完成後,即可先行登入後取得Account ID(帳號ID)及License Key(使用金鑰)等資訊,以供後續設定使用,如圖1所示。
圖1 登入後取得帳號ID和使用金鑰。
緊接著執行如下的指令,安裝更新地理資料庫的管理程式,名稱為「geoipupdate」:
dnf install geoipupdate
安裝完成後,即可使用geoipupdate程式來取得並更新最新版本的地理資料庫。在使用geoipupdate之前,先設定組態檔(/etc/GeoIP.conf),主要設定下列組態值即可(其中#為註解說明):
AccountID [帳號ID] #在登入maxmind後取得 LicenseKey [使用金鑰] #在登入maxmind後取得
接著,設定所要下載的地理資料庫名稱,在此僅下載精簡版本的國家(GeoLite2-Country)和城市(GeoLite2-City)的地理資料庫:
#設定下載精簡版本的地理資料庫 EditionIDs GeoLite2-Country GeoLite2-City #設定地理資料庫置放的目錄位置 DatabaseDirectory /usr/local/ share/GeoIP
完成設定後,使用以下的指令來執行更新,-f:為指定組態檔的位置:
geoipupdate -f /etc/GeoIP.conf
更新完成後,在「/usr/local/share/GeoIP」目錄下應該就會有GeoLite2-City.mmdb和GeoLite2-Country.mmdb地理資料庫檔案。
接著,可利用mmdblookup來測試地理資料庫是否正常(將IP轉換成地理區域資訊),執行如下指令,其中--file指定地理資料庫檔案的位置,而--ip為測試的IP:
mmdblookup --file /usr/local/share/GeoIP/ GeoLite2-City.mmdb --ip 168.95.1.1
在正常的情況下,將會回覆一個JSON格式的回覆資訊(內容包含此IP所屬的城市和國別等資訊)。在安裝好地理資料庫與管理程式後,接著就能安裝mod_maxminddb(在此版本為1.3.0)。本文假設已安裝Apache伺服器並安裝於「/usr/local/apache2/」目錄,所以執行如下的安裝指令:
#取得mod_maxminddb的原始碼 wget https://github.com/maxmind/mod_ maxminddb/archive/refs/tags/1.3.0.tar.gz
在解壓縮後,至其原始碼的目錄並執行下列指令:
bootstrap #重新建立編譯環境設定
由於要編譯成Apache網站伺服器所使用的模組,因此必須使用--with-apxs來指定apxs程式的位置,指令內容如下:
configure --with-apxs=/usr/local/ apache2/bin/apxs
然後,以make指令進行編譯(Compiler)。編譯成功後,即可利用「make install」來安裝相關模組。如果一切正常,完成安裝後,在「/usr/local/apache2/modules/」目錄下將會產生名稱為「mod_maxminddb.so」的模組程式。
mod_maxminddb.so常用組態
以下說明mod_maxminddb.so常用組態:
設定是否啟用IP對應地理位置的查詢。
設定以變數名稱來儲存地理位置資料庫的位置。例如「MaxMindDBFile COUNTRY_DB /usr/share/GeoIP/GeoLite2-Country.mmdb」,是以變數名稱為COUNTRY_DB來表示GeoLite2-Country.mmdb。
設定以變數來儲存以IP(網站的來源連線IP)查詢到的地理區域資訊,也就是將查詢地理資料庫的結果儲存至變數中,而後續網站伺服器(Apache)可針對此變數進行相關的存取控制。例如「MaxMindDBEnv MM_COUNTRY_CODE COUNTRY_DB/country/iso_code」,其中COUNTRY_DB為地理資料庫名稱,country/iso_code為資料路徑,表示取得地理資料庫(GeoLite2-Country.mmdb)內的國家代碼(iso_code)資訊,並將此資訊儲存在名稱為MM_COUNTRY_CODE的變數中,後續即可針對MM_COUNTRY_CODE設定相關規則進行連線的管控。
由於地理資料庫的儲存方式採用json的階層格式,因此county/iso_code表示取得國家代碼的資訊,如圖2所示,在本例中,國家代碼為TW,以此類推,如果想取得國家的英文名稱,可使用country/names/en來取得(本例為Taiwan)。
圖2 地理資料庫的儲存方式採用json的階層格式。
說明過相關組態的用法後,最後使用mod_maxminddb模組實作一個利用地理區域來管控來源IP的機制。為了測試方便,這裡以封鎖來自台灣的連線IP為例。
相關Apache組態說明
由於是利用Apache的管控機制進行來源連線的控管,因此在設定之前,先簡單說明相關的Apache組態:
此組態是針對來源欄位,建立比對的規則(可使用正規表示法),如果規則成立,便會建立一個變數,後續即可利用此變數,制定相關管控連線規則。例如「SetEnvIf MM_COUNTRY_CODE ^(TW)$ BlockCountry」,表示當MM_COUNTRY_CODE變數內容為TW時,便符合所設定的規則,此時會建立一個名稱為BlockCountry的變數。
〈RequireAll〉…〈/RequireAll〉
此組態可設定是否允許來源IP的連線,必須在此區段中所有設定的規則均符合,才會允許連線,其設定語法為:
Require [條件式]
其常見的規則設定,如下所示:
Require all granted:表示允許所有來源的連線,一般而言,通常會先預設此規則,後續再設定欲管控的限制規則。 Require all denied:表示拒絶所有來源的連線。 Require [設定IP]:表示僅允許來源為[設定IP]的連線。 Require env [變數名稱]:表示如果所設定的變數存在,才可允許連線。 Require not env [變數]:表示如果所設定的變數不存在,才可允許連線。在本文中,便是利用此規則來完成管控措施。
動手實作測試
了解會使用到的相關組態用法後,接著以限制來自「台灣」的連線為例,完成地理位置管控的功能。可在Apache的組態設定檔「httpd.conf」內加入下列的設定(其中#為註解說明):
#設定載入mod_maxminddb模組 LoadModule maxminddb_module modules/mod_maxminddb.so 〈IfModule mod_maxminddb.c〉 MaxMindDBEnable On #啟用IP轉地 理區域資訊的功能 #設定以COUNTRY_DB變數來表示地理 資料庫的位置 MaxMindDBFile COUNTRY_DB /usr/ local/share/GeoIP/GeoLite2-Country.mmdb #以MM_COUNTRY_CODE變數來儲存來 源IP轉換過後的國別代碼 MaxMindDBEnv MM_COUNTRY_CODE COUNTRY_DB/country/iso_code 〈Directory /usr/local/apache2/htdocs〉 #針對網站根目錄(Documentroot)進行設定 #如果MM_COUNTRY_CODE變數內容為TW 即建立名稱為BlockCountry的變數 SetEnvIf MM_COUNTRY_CODE ^(TW)$ BlockCountry 〈RequireAll〉#需符合下列所有規 則,方可進行連線 #預設所有來源均可連線 Require all granted #設定當BlockCountry變數存 在即拒絶連線 #由於來源IP轉換過後的國碼為TW 時就會產生BlockCountry變數,因此 此規則是設定拒絶來自台灣的連線 Require not env BlockCountry 〈/RequireAll〉 〈/Directory〉 〈/IfModule〉
設定完成後,重新啟動Apache網站伺服器,此時即可拒絶所有來自台灣的連線。
<本文作者:吳惠麟,多年資安經驗,喜好利用開源碼建構相關解決方案,著有「資訊安全原理與實驗」等書。>