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

2017年6月14日 星期三

AWS 筆記 - AWS ELB 與 Nginx 之 DOS 惡意攻擊者的處理方式

這個緣由是這樣的,有一台 Server 被狂打,但架構是:

Remote client <-> AWS ELB <-> Web server (Nginx) <-> Application

當有用戶非常好心地發大量 request 來檢查機器漏洞,若 Nginx 預設都沒多做設定,那 access.log 都會只記錄到 AWS ELB IP ,也就是不能把 access.log 紀錄的 IP 拿來 ban ,會變成 ban 掉 ELB。

而 AWS 提供的 Security group 預設是從 Allow 的角度,若要特意 ban 掉某個 IP 會有點難搞,例如要改寫防火牆規則,因此,最後就改成從實體 server 去阻擋遠端 client request 了。

步驟一:先讓 Nginx 可以記錄到真實的 remote ip

/etc/nginx/nginx.conf

http {
    # ...
    real_ip_header X-Forwarded-For;
    set_real_ip_from 0.0.0.0/0;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    # ...
}


如此一來,access.log 的 remote_addr 就可以不是 AWS ELB IP 了。

步驟二:用 Nginx 去 deny ip

/etc/nginx/conf.d/your-service.conf

server {
  # ...
  deny RemoteIP;
  # ...
}


這樣設定後,在用 sudo nginx -t 檢查語法後,就可以啟用了

在此不用 iptables 去阻擋的主因是封包進來的 IP 都是 AWS ELB ,所以才改從 Nginx/App 這層取阻擋。缺點就是 access.log 還是一直肥,好處是可以觀察 access.log 看看對方是不是放棄攻擊了?XD

未來若碰到 DDOS 就...

2016年7月27日 星期三

Microsoft Azure 管理筆記 - 仿 AWS 使用 Load Balancer (Azure: Load Balancer/Availability Set)

以 AWS 來說,部署服務會想要用 Auto Scaling 搭配 Load Balancer 來達成 high availability 的架構,而 Load Balancer 扮演著將 requests 導向至一群機器。就 Azure 的服務情況,拆解後包括 Availability Set、Load Balancer 項目。

以把玩的流程來看,需要先搞懂 Availability Set,其建置流程包括 Fault domains 跟 Update domains 關鍵字(可以參考這篇完整介紹 Azure Exam Prep – Fault Domains and Update Domains )

azure_try_to_move_into_aset

接著,在 Availability Set 中添加一台機器(沒機器時,Load balancer 無法設定),這步只能在新開機器時設定,不能對已經開啟的機器設定。

透過新增機器時,設定 Availability Set:
New -> Virtual machine -> Create -> 基本設定後, 在第三步 Settings - Availability 項目中,可以指定 Availability Set。
建置完後,緊接著建立 Load Balancer,建完後在其 Load Balancer -> Settings -> Backend pools -> Add a virtual machine -> Availability Set -> 挑選剛剛建立的 Availability Set(若 Set 裡沒機器,則會無法挑選!)-> 挑選裡頭的機器!

azure_lb_probes

azure_lb_rules

接著處理 requests 導向問題,例如開放 HTTP 80/443, TCP 22 port:
Load Balancer -> Settings -> Probes: 這就像 AWS Load Balancer 檢查某端口服務是否正常
Load Balancer -> Settings -> Load balancing rules: 正式把 requests 導向給後端機器群
azure_vm_network_security_group

此外,別忘了對剛剛建立的 VM 設定好防火牆(Network security group, 如 VM -> VM Settings -> Network interface -> settings -> )
Network security group -> Settings -> Inbound security rules (有需要可以在設定 Outbound security group),例如預設有開通 22 port ,此時就只需再添加 80, 443 port
如此一來,當 Load balancer 的 probes 檢驗通常順暢後,就可以對 load balancer 送資料試試了。

檢驗流程:
  1. 先檢查 VM 是否運作正常,如有 public ip 就從外面測試 telnet vm_ip port 做檢查,可以先裝個 nginx 或用 sudo python -m SimpleHTTPServer 443 / sudo python -m SimpleHTTPServer 80 應急一下
  2. 對 Load balancer 檢驗,如 telnet load_balanacer_ip port
以上則完成 AWS Load balancer 建置。

2016年2月18日 星期四

AWS 筆記 - Godaddy 續約憑證 (HTTPS/SSL) 以及 Load Balancer 憑證更新方式

AWS ELB Certificate

購買了每兩年更新一次的憑證服務,然而,憑證更新的原理是所有機器的憑證都會替換掉的。所幸更新憑證時,新舊憑證都會共存的,而 Godaddy 給予 90 天的區間來處理。

官方文件:https://tw.godaddy.com/help/ssl-864
您需要執行幾個步驟後方能續約 SSL,續約操作視憑證類型及網站託管地點而定。 即使您的 SSL 是自動續約,您也需要套用續約積分,並透過帳戶完成續約請求。
您可以在 90 天續約窗口期內購買及套用 SSL 續約: 過期前 60 天至過期後 30 天內。
例如,若您的憑證在 6 月 15 日過期,則您必須在 4 月 15 日至 7 月 15 日間購買並套用續約積分。
在您購買續約積分或您的 SSL 自動續約後,您必須將積分套用至即將過期的 SSL,並完成續約請求。 倘 SSL 過期且您沒有在 90 天續約窗口期內完成續約請求,則之前正常的網站會出現錯誤訊息。
先走一輪 Godaddy 設定:
  1. 在 https://certs.godaddy.com/cert 挑選要續約的憑證,可以看有效日期 
  2. 檢視狀態
  3. 狀態: 續約憑證 -> 點擊後則是一些簡易流程、送單
  4. 接著就只需等待,大概10分鐘內,可以在 https://certs.godaddy.com/cert 看到有效日期被拉長了
  5. 進去檢視憑證,接著下載新的憑證資料(以 Apache 來說,內容物就 gd_bundle-g2-g1.crt 和 yourdomain.crt 兩個檔案)
接著 AWS ELB 的設定:
  1. 在 EC2 -> Load Balancers -> 挑選指定 ELB
  2. 切換至 Listeners 分頁 -> SSL Certificate -> 點選 Change 就可以上傳新的憑證資料
若有其他 ELB ,則直接 Change 到新設定的即可。

2015年11月4日 星期三

[PHP] 把玩 PHP AWS SDK - 列出 EC2 指定規格列表、 ELB 底下的機器列表 @ Ubuntu 14.04

之前用一些 tool-based 的工具做了一些事情,例如呼叫完指令再動態抽 JSON 資料:
  • $ aws elb describe-load-balancers --load-balancer-name "XXX"
  • $ aws ec2 describe-instances --instance-ids  "XXX"
來試試 AWS SDK 來做事吧,先挑 PHP !

為了高移植性,我採用下載 aws.phar 的模式:
接著則是簡單的登入資料填寫一下:

<?php
require 'aws.phar';

$config = array(
'version' => 'latest',
'credentials' => array(
'key' => 'key',
'secret' => 'secret',
),
'region' => 'us-west-2',
);


列出 EC2 - m1.small instance:

<?php
$ec2Client = Aws\Ec2\Ec2Client::factory($config);

// http://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.Ec2.Ec2Client.html
$result = $ec2Client->DescribeInstances(array(
        'Filters' => array(
                 array('Name' => 'instance-type', 'Values' => array('m1.small')),
        )
));

print_r($result);


想要列出 EC2 - 指定 Load Balancer 下的機器:

<?php
$client = Aws\ElasticLoadBalancing\ElasticLoadBalancingClient::factory($config);
$result = $client->DescribeLoadBalancers( array(
        'LoadBalancerNames' => array('Load Balancer Name')
));
print_r($result['LoadBalancerDescriptions'][0]['Instances']);
print_r($result);


其中,雖然 $result 都是 Aws\Result Object ,且裡頭都是 [data:Aws\Result:private] => Array ,但可以透過 array access 的方式去存取囉。

接下來就可以試試連續動作,從 ELB 得知機器後,再得到機器的 public ip:

<?php

require 'aws.phar';

$ELB_NAME = 'XXXX';
$client = Aws\ElasticLoadBalancing\ElasticLoadBalancingClient::factory($config);
$result = $client->DescribeLoadBalancers( array('LoadBalancerNames' => array($ELB_NAME)));
if (isset($result['LoadBalancerDescriptions']) && is_array($result['LoadBalancerDescriptions']) && count($result['LoadBalancerDescriptions']) && isset($result['LoadBalancerDescriptions'][0]['Instances'])) {
$instances = $result['LoadBalancerDescriptions'][0]['Instances'];
//print_r($instances);
$ec2_id = array();
foreach($instances as $ec2)
if (isset($ec2['InstanceId']))
array_push($ec2_id, $ec2['InstanceId']);
if (count($ec2_id) > 0) {
$client = Aws\Ec2\Ec2Client::factory($setup);
$result = $client->DescribeInstances(array(
'Filters' => array(
array('Name' => 'instance-id', 'Values' => $ec2_id),
)
));
}
$public_ip = array();
if (isset($result['Reservations'])) {
foreach($result['Reservations'] as $target) {
//print_r($target['Instances'][0]['PublicIpAddress']);
array_push($public_ip, $target['Instances'][0]['PublicIpAddress']);
}
}
//print_r($result['Reservations']);
print_r($public_ip);
}

2015年5月14日 星期四

AWS 筆記 - 關於 Amazon EC2、Elastic Load Balancer (ELB)、Auto Scaling 與 CPU loading 過低問題 @ Ubuntu 14.04, Apache 2.4

使用 ELB + Auto Scaling 好一陣子了,最近因為服務量變大導致 Web Server 變多,然而,在部署程式方面就累了許多,因此朝 Scaling up 來進行一下,限縮機器數量並提升機器規格。

在這個過程中,從 m3.medium 改到 m3.large 或 m3.xlarge 等,卻發現越高級的機器,其 CPU Loading 衝不上去,並且限縮機器後導致服務極為不穩,連 Health check 也發現。但明明機器都不忙啊?!

接著因為非常忙,拖了兩個禮拜才正視這個問題。追了許多後,發現...只是 Apache Multi-Processing Module (MPM) 設定未同步拉高 XD 好蠢的一件事啊。此外,由於服務眾多,尚未有空最佳化,就先繼續用 prefork 架構了。

$ apache2 -v
Server version: Apache/2.4.7 (Ubuntu)
Server built:   Mar 10 2015 13:05:59
$ sudo vim /etc/apache2/mods-enabled/mpm_prefork.conf
<IfModule mpm_prefork_module>
        ServerLimit                7500 # 預設才 256
        StartServers               20
        MinSpareServers           15
        MaxSpareServers            50
        MaxRequestWorkers          7500 # 預設才 256
        MaxConnectionsPerChild     0
</IfModule>


總之,ServerLimit 跟 MaxRequestWorkers 就看當下的機器資訊,例如記憶體等等。

透過 Web server 執行的環境調整,機器的負載度自然可以提升,接著 Auto Scaling 的機制就可用啦!原先在 m3.medium 的機器是單核,而在 m3.large 開始就是多核心了!效能就能更往上衝囉。很妙地用系統預設的 prefork.conf 在 m3.medium 還混的不錯 :P 包含 CPU 會依照 requests 量變化,不像同樣的設定檔搬到多核心後就失效了,CPU 衝不起來,導致 Auto Scaling 也失效!

整體上,這次碰到 service 不穩的主因:

total requests 一直保持一個數量,而原先開 m3.medium x N ,想說機器提升成 m3.large 就把數量調整成一半,結果 web server 數量降低,再加上 prefork.conf 的設定,導致能服務的 requests 量也降低!而 Health check 無法正常被驗證,接著 AWS Scaling 會判斷機器出事要下線,甚至 requests 不導過去,頻頻出現:

503 Service Unavailable: Back-end server is at capacity

如今終於解掉了 :P Health check requests 也能被服務到,機器自然就不會被判斷成有問題,自然就解掉 503 Service Unavailable 現象。

最後,如果要追蹤網路流量,可以試試 nload 這個指令,看整體流量還滿方便的。

2015年4月28日 星期二

AWS 筆記 - 關於 Load Balancers 之 Health Check 處理心得

若是 web server,通常 Health check 都是定期去請求 /index.html 是否正常,以此來判斷服務是否正常。而檢查 /index.html 有很多含義,例如當 server response time 超過 10 秒,也能標記為不正常等。

最近碰到一個案例,是在處理外包案時,發現對 / 或 /index.html 時,一直不正常,但用瀏覽器去看又覺得無恙,例如用 wget -d 也行,最後發現用 telnet 看到問題 XD

$ telnet server_ip 80
GET / 或 GET /index.html


接著看到一些 PHP 噴 error message。

發現,外包在一些設定檔內,透過判斷 $_SERVER['HTTP_HOST'] 是不是他們家的 server ,以此決定開啟 debug mode。

<?php
if ($_SERVER['HTTP_HOST'] == 'xxx.yyy.com') {
    $is_test_server = true;
} else {
    $is_test_server = false;
}


這件事大概只能透過 telnet 等不送 HTTP header 要求時,才會發現的 bug。這個 bug 還滿好解的,例如加上一些 isset($_SERVER['HTTP_HOST']) 等,但有一些 PHP framework 使用上會要求提供網址位置,例如:

<?php
$protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
$config['base_url'] = $protocol . '://' . $_SERVER['HTTP_HOST'] . '/';


這時又只能再爆一次。若有心解決,就繼續改 code ,無心解決的話,可以把一些 error message 都關掉,或是把 Health check 改成 TCP 80 模式吧 XD

2014年6月25日 星期三

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年5月7日 星期三

AWS 筆記 - 使用 Amazon EC2 進行 Deploying Web services

稍微把玩 AWS Elastic Load Balancing 跟 Auto Scaling 後,大概有一點粗淺的心得:
  • 開一台機器,如 micro 等級,並設定這台機器關機也不下線,可專門用於製作 AMI
  • EC2 micro 採用 EBS 管理,每一次製作 AMI 會產生新的 EBS snapshot,記得定時去清理
  • 程式碼若是透過 git 管理,可以在 /etc/rc.local 上設定開機自動更新方式,至少 AMI 不是最新程式碼時也還能堪用(但 git server 掛了就...)
  • 如果想要透過 web cgi 更新,記得把 source tree 的 owner 或 group (搭配775方式) 設定 www-data,可以用 sudo -u www-data /tmp/update.sh 進行測試
AWS Elastic Load Balancing:
  • 使用 AWS ELB 時,可以讓多台機器綁定在固定的 DNS Name,記得需要處理一下多台機器進行切換其 Session/Cookie 問題,例如單純的使用情境,可以透過設定 Stickiness: LBCookieStickinessPolicy, expirationPeriod='600' 等方式來應付等
  • 對於有使用 HTTP Authentication 的 web server 而言,因為帳密是一直隨 browser 傳給 web server 的(就像 cookie一樣),所以 ELB 再切換機器時,不會因機器不同台而再次詢問帳密
AWS Auto Scaling:
  • 對 Auto Scaling 而言,預設機器都是關機後就下線,除非改掉預設方式,不然更新系統時 reboot 的結果就是開一台新機器,此外,把 Auto Scaling Group 刪掉等同把機器都下線
  • 透過製作新的 AMI 來取代系統更新時,而原先設定好的 Auto Scaling Launch Config 不能更新採用的 AMI,但可透過新增新的 Launch Config 後,更新 Auto Scaling 設定後,再刪掉舊的 Launch config 等

2014年4月29日 星期二

AWS 筆記 - Amazon EC2 Auto Scaling 與 Elastic Load Balancing

整體流程:
  1. 建立 My AMI (www-service-auto-scaling-ami)
    • 順便準備一些會提升 CPU 使用率的程式
  2. 建立 ELB 規則 (www-service-auto-scaling-elb)
  3. 建立 Auto Scaling 規則
    • 建立 Launch 機器的規則 (www-service-auto-scaling-launch-conf)
    • 建立 Auto Scaling 規則 (www-service-auto-scaling-group)
      • 建立 新增機器 Alerm 規則 (CPU 平均高於 50%)
      • 建立 減少機器 Alerm 規則 (CPU 平均低於 30%)
首先,建立 My AMI 是因為開機器時要以自己的服務為主



建立 Elastic Load Balancing 規則,因為到時候打算對 ELB 新增機器,而非對 EC2,此外,這時建立 ELB 時,可以不用套用在任何機器上



點選建立 Auto Scaling 規則,但在這之前需要設定 launch 機器規則,例如要挑哪個 AMI 等:












設定 launch 規則後,正式進入 Auto Scaling 規則,這邊主要需設定新增機器、降低使用機器的條件,也可以設定 email notification 通報機器增減訊息等。












當 Auto Scaling Group 設定完後,將會立即依照設定開啟機器(同理刪除 Auto scaling group 也就會把機器都關掉),例如設定為最少2台,那就會馬上開2台出來。接著,可以在 ELB 或 Auto Scaling 頁面觀察機器狀態,其中在後者還能更新開關機器的條件,並且把上執行等。











 

至於如何測試自否自動 Scaling 的部分,此例我是搭配 ELB 測試,對指定網址瀏覽時,除了顯示 /etc/hostname 資訊來測試是否有不同外,還透過 CGI 執行一隻背景程式來讓 CPU 使用率衝到 100% ,透過這樣的做法,即可以觀察 Auto scaling 是否正常運行,亦可翻閱 Auto scaling history 查看更動。

<?php
shell_exec( 'echo "<?php while(1) ; " | php > /dev/null 2>&1 &' );

@date_default_timezone_set("Asia/Taipei");
$current_datetime = @date('Y-m-d H:i:s', @time());
echo "Service @ $current_datetime:".file_get_contents('/etc/hostname')."\n";

AWS 筆記 - 使用 Amazon Elastic Load Balancing 與 SSL/HTTPS (GoDaddy) 設定



首先,先開一台 EC2 機器,架設一下 HTTP/HTTPS,設定完就建一個 AMI 保存起來,再從 My AMI 再多開一檯出來(記得要擺在同一個 Availablility Zone才行),變成有兩檯 EC2 機器正在運行。此外,若 SSL 憑證有第三方簽證,而對於 EC2 上的機器,其 SSL 憑證可以不必用第三方簽證,只要在 Elastic Load Balancer (ELB) 上頭是第三方簽證的就夠用了!讓管理方便許多。

接著設定 ELB 吧,比較需要留意是 SSL 的設定,其中 DNS 跟 SSL 憑證是委託 GoDaddy 維護的,所以先從 GoDaddy 取得 SSL 憑證吧,大概會有三個檔案:
  • xxxxxx.crt
  • gd_bundle-xxxx.crt
  • xxxxxx.key



此時在填寫資料時,在 Public Key Certificate 就是 xxxx.crt ,而 Certificate Chain 就是 gd_bundle-xxxx.crt ,比較麻煩一點的是 Private key 那塊,需要稍微轉換 xxxxx.key

$ openssl rsa -text -in *.key

再把 -----BEGIN RSA PRIVATE KEY----- 到 -----END RSA PRIVATE KEY----- 裡的資料貼上即可。如此一來即可完成 SSL 設定。其他的步驟就沒什麼難的。



設定要用來監控判斷機器狀況的檔案:





挑兩檯機器以上吧:






設定好後就會得到一個網址可以連,此網址就會動態調整 requests 到數檯機器上:



此外,若有機器 out of service 時,也能觀測或動態刪減,十分方便:



其他筆記:
  • 關於 SSL / HTTPS 的部分,記得去申請個 CNAME Record 來對應到 ELB 的網址,如此一來,使用者逛網頁時就不會彈跳出不會彈跳出憑證問題
  • 關於如何測試 ELB 到底有沒有動態調整 requests 的部分,建議可以寫一隻 PHP 讀 /etc/hostname 出來,接著就可以透過 ELB 網址瀏覽,觀察讀出來的 hostname 是否有在變化

    $ cat index.php
    <?php
    @date_default_timezone_set("Asia/Taipei");
    $current_datetime = @date('Y-m-d H:i:s', @time());
    echo "Service @ $current_datetime:".file_get_contents('/etc/hostname')."\n";