2014年6月25日 星期三

[Linux] Apache/GeoIP/mod_geoip: 依據 Client IP Country 回傳指定 Server Location @ Ubuntu 14.04、Apache 2.4.7

$ apt-cache show libapache2-mod-geoip
Package: libapache2-mod-geoip
Priority: optional
Section: universe/web
Installed-Size: 86
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Prach Pongpanich <prachpub@gmail.com>
Architecture: amd64
Version: 1.2.8-2
Depends: apache2-api-20120211, libc6 (>= 2.3.4), libgeoip1
Filename: pool/universe/liba/libapache2-mod-geoip/libapache2-mod-geoip_1.2.8-2_amd64.deb
Size: 18748
MD5sum: fc16528f6d8acabaf8d40c70fe47b1b2
SHA1: 457df303c09556297a8b1f6887fe7a901d8bd063
SHA256: 26eabfe728014a506186f2856a3149f00e7bfcb6db9226dbfe13976ab3b4d584
Description-en: GeoIP support for apache2
 This is an apache2 module for finding the country that a web request
 originated from. It uses the GeoIP library and database to perform
 the lookup. The module allows manipulation of client requests from within
 Apache based on the country of origin.
 .
 This module only works on Apache 2 servers.
Description-md5: e4085008663af571952df21045e8534a
Homepage: http://www.maxmind.com/app/mod_geoip
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Origin: Ubuntu

$ sudo apt-get install libapache2-mod-geoip

$ ls -la /usr/share/GeoIP/
total 3852
-rw-r--r--   1 root root  827301 Apr  7 14:20 GeoIP.dat
-rw-r--r--   1 root root 3105495 Apr  7 14:21 GeoIPv6.dat


基本上安裝完就等同啟動 mod_geoip ,可以在 /etc/apache2/mods-enabled 看到 geoip.conf, geoip.load 蹤影。

編輯 Apache configure file:

<IfModule mod_geoip.c>
        GeoIPEnable On
        <IfModule mod_rewrite.c>
                RewriteEngine On
                RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^CN$
                RewriteRule ^(.*)$ http://example.com.cn$1 [L]
        </IfModule>
</IfModule>


如此一來,當 Client IP 判斷是 CN 時,透過 Web Server 導向 CN 區的機器。

使用這招的目的是...大陸架設服務時,需要"備案",在備案還沒通過時,使用 domainname 連線過去的機器會被 ban 掉,這時候可以先稍微用已備案的或是 IP 來頂替了。

當備案成功後,就可以大方地使用 GeoDNS 的解法,讓使用者不必先連到指定機器再轉址。

最後,如果要留一些 debug 模式,可以多加上 hostname 的判斷,限定特定 hostname 才會依照使用者 IP 位置轉址。

<IfModule mod_geoip.c>
        GeoIPEnable On
        <IfModule mod_rewrite.c>
                RewriteEngine On
                RewriteCond %{HTTP_HOST} .
                RewriteCond %{HTTP_HOST} ^www\.example\.com$
                RewriteCond %{ENV:GEOIP_COUNTRY_CODE} ^CN$
                RewriteRule ^(.*)$ http://www.example.com.cn$1 [L]
        </IfModule>
</IfModule>


參考資料:

AWS 筆記 - 透過 AWS CLI 取得指定 ELB 下的所有機器的 Public IP @ Ubuntu 14.04

基於 deploying 需求,希望能夠得知指定 ELB 下的機器列表,再搭配 ssh keyfile 進行動作,以此降低人工部分,所以就需要用用 aws cli 啦,不然完全從 web ui 大多都能滿足一些操作手法。

關鍵兩個 aws cli 用法:
  • $ aws elb describe-load-balancers --load-balancer-name YourELBName
  • $ aws ec2 describe-instances --instance-ids YourEC2InstanceID
相關 AIM 權限:
  • elasticloadbalancing:DescribeLoadBalancers
  • ec2:DescribeInstances
使用 PHP 連續動作:

<?php
define("AWS_ELB_NAME", "YourELBName");

$elb_servers_public_ip = array();
$elb_info = @json_decode(@shell_exec("aws elb describe-load-balancers --load-balancer-name ".AWS_ELB_NAME), true);
if(isset($elb_info['LoadBalancerDescriptions'][0]['Instances']))
{
foreach( $elb_info['LoadBalancerDescriptions'][0]['Instances'] as $ec2_instance )
{
foreach( $ec2_instance as $ec2_id )
{
$ec2_info = @json_decode(@shell_exec("aws ec2 describe-instances --instance-ids $ec2_id 2>/dev/null"), true);
if(isset($ec2_info['Reservations'][0]['Instances'][0]['PublicIpAddress']))
array_push($elb_servers_public_ip, $ec2_info['Reservations'][0]['Instances'][0]['PublicIpAddress']);
}
}
}
print_r($elb_servers_public_ip);


其他心得:

雖然 aws ec2 describe-instances 可以一次查詢多筆,但是不知為何 aws elb describe-load-balancers 回傳的 instances 卻也有可能出現不存在的機器,這時透過 aws ec2 describe-instances 查詢多筆資料時,就會回傳機器不存在的訊息,得不到想要的資料,只好改成迴圈一筆一筆地問。

2014年6月24日 星期二

[Linux] 開機啟動時,執行 rsync 任務 @ Ubuntu 14.04

原先在 /etc/rc.local 執行,但不知為何 rsync 任務一直未被執行,且開機成功後,用 root 權限或其他角色測試執行 /etc/rc.local 卻又一切正常。有一說法是一開始可能網路未初始化,但很妙地我在 /etc/rc.local 執行 git pull 又很正常。

暫時還搞不懂出錯的地方,外加機器重開機太耗時間了 XD 先拿 crontab @reboot 的方式來頂替了。

# m h dom mon dow command
@reboot sudo /path/rsync_job.sh &


有這個需求是在 AWS 使用 Auto Scaling 時,機器會因為條件式而被關閉、重開新的,為了確保新開的機器上頭的程式碼仍夠是最新版,所以分別試用 git pull 跟 rsync 來更新。

2014年6月20日 星期五

AWS 筆記 - Amazon Route 53 GeoDNS 用法 (Routing Policy: Latency)



想要讓不同 client 查詢統一個 Domain 時,回應離使用者近的 Data Center 的機器嗎?恰好 AWS 有提供這個功能,用法:
  • 將各個 Data Center 的機器,透過 A Record 指定一個 Domain Name
  • 將使用者真正查詢對象(DomainName)設定多筆 CName Record 對應,在新增時,選擇 Latency 並挑選區域即可,例如服務亞洲可以挑日本(ap-northeast-1), 其他地方挑美國(us-west-1)等,更多區域資訊請查詢:AWS Regions and Endpoints

接著,測試時,可以透過 nslookup 來指定要查詢的 DNS Server 來模擬不同區域的查詢結果,如 Google 8.8.8.8 和最近阿里雲對外公佈的新服務 ALiDNS 235.5.5.5,就可以看到因為地域的不同產生的變化。

連續動作:
  1. 新增 A Record: www-geo-jp.changyy.org/1.1.1.1
  2. 新增 A Record: www-geo-us.changyy.org/2.2.2.2
  3. 新增 CName Record: www-geo.changyy.org/www-geo-jp.changyy.org/Latency/ap-northest-1
  4. 新增 CName Record: www-geo.changyy.org/www-geo-us.changyy.org/Latency/us-west-1
查詢:

$ nslookup www-geo.changyy.org 223.5.5.5
Server:         223.5.5.5
Address:        223.5.5.5#53

Non-authoritative answer:
www-geo.changyy.org       canonical name = www-geo-jp.changyy.org.
Name:   www-geo-jp.changyy.org
Address: 1.1.1.1

$ nslookup www-geo.changyy.org 8.8.8.8
Server:         8.8.8.8
Address:        8.8.8.8#53

Non-authoritative answer:
www-geo.changyy.org       canonical name = www-geo-us.changyy.org.
Name:   www-geo-us.changyy.org
Address: 2.2.2.2


別忘了,這種功能是需要額外收費的。

Amazon Route 53 Pricing:
  • Standard Queries
    • $0.500 per million queries – first 1 Billion queries / month
    • $0.250 per million queries – over 1 Billion queries / month
  • Latency Based Routing Queries
    • $0.750 per million queries – first 1 Billion queries / month
    • $0.375 per million queries – over 1 Billion queries / month

AWS 筆記 - 從 Godaddy 搬到 AWS Route 53



AWS Route 53 有很多收費機制,但為了 GeoDNS 的使用,開始來搬遷。原先購買的 Domain name 是在 Godaddy 上購買以維護的,整個匯出流程還滿容易的。

  1. AWS Route 53: Create Hosted Zone

  2. AWS Route 53: Import Zone File

  3. Godaddy: Export DNS Setttings

  4. AWS Route 53: Import Zone File 貼上需要的,如 A系列、CNAME系列、MX系列等

  5. Godaddy: Set NameServer,改用 AWS Route 53 提供的清單



最後,可以用 dig 去追蹤看看,是不是真的改用 AWS Route 53 提供的 NS 囉

$ dig +trace example.com