2013年5月26日 星期日

DNS 服務,你對於 DNS 懂多少?


DNS 安全性,開發者必知


DNS - Domain Name System,簡單的說,在網際網路上的各式主機不論IPv4或IPv6均以IP位置為識別,而DNS就是提供網際網路上IP與名稱對應的一套系統,提供大家可以透過好記的名稱來找得到服務提供主機的一個方式,後面將會從自己經驗分享 DNS 安全性問題,以及 DNS 的基本保護方式,當然『安全』從你我開始


先了解...



了解DNS之前,有些專有名詞需要再重新了解一下...


  • IP位置 - 一個識別網際網路上唯一存在的ID,要提供服務的主機都需要有對應到網路上可存取的一個IP位置,相當於一個入口,讓我們可以訪問需要的服務。
  • 協定(Protocol) - 可以想像成馬路的分類,可以給機車走的、單車走的、汽車走的、大卡車走的都不一樣,同樣的,網際網路上有HTTP走的、HTTPS走的、FTP走的...都是一些溝通的協定,背後也有自己的一個溝通的定義。
  • 網域名稱(Domain Name) - 代表著一個或一組IP位置的名稱,使用網際網路的使用者可以透過這個名稱找到相對應的伺服器存取服務。
  • 網址(URI / URL) - 一般我們稱的網址 = 協定+網域名稱+資源位置,類似:http://www.google.com/drive就是個網址的實例,我們透過他來存取對應的資源。


簡述DNS的運作原理



一般使用者了解到IP的機制後,大致上想得到每次網址列打上網址(就是domain name),下面一個最簡單的實例,當使用者瀏覽器上打上某個網址時,電腦會解攜出欲訪問的網域名稱,並且透過DNS系統查詢該網域名稱真實的IP位置後,再結合網址的資源位置直接訪問實際資源所在的位置(此時已經定位出實際IP位置,並連線該IP查詢定義位置中的資源)...






圖一、訪問網路資源概念圖


而網際網路上不是只有一台DNS Server,一般私有網路大多自己架設內部的DNS Server,以提供內部查詢使用,作用上,一方面是方便將特定私有往段服務IP定義逾期上,以提供內部使用,另一方面則是透過DNS Cache機制,讓服務的存取可以更加快速。圖二是以內部網路為例,存取網路資源時候DNS查詢的流程,而一般設定DNS時候,都會設定轉查的路徑,例如我信任Google的DNS服務,那我就會設定我的上一層DNS為8.8.8.8或8.8.4.4(此兩個IP為Google的DNS位置),所有超過我這台DNS伺服器所能回答的問題,都將往上詢問上一層DNS Server,由他回答...



圖二、內部DNS服務


而DNS詢問網域名稱的實際過程卻又複雜過圖二所交代的,實際上打上一個網域名稱,則第一層DNS向上詢問不果的時候,DNS server會去詢問該domain的root dns server(一般root dns server會定義在DNS server上),然後由root dns回應該domain是隸屬於哪台DNS server管轄,之後該DNS server就會記住這個對應,日後有該domain的DNS問題就都會詢問這個網域管理的DNS server。而這奇妙的一切,都是設定在DNS server中... 不過這邊不講設定,了解一下概念,如圖三所示:



圖三、DNS的階層是查詢(1)

最後一種情況是當DNS Server有設定子網域的時候,查詢到該網域的所屬DNS server後,該DNS server會轉查子網域負責的DNS server,再將查詢結果IP往上回傳... 圖四是說明這樣狀況的詢問流程:



圖四、DNS的階層是查詢(2)


失守DNS Server的風險


談到這邊,大致上可以猜想得到如果不幸DNS Server掛點,無法提供回應的時候,網路上將會無法解析您服務的真正位置,也就是說服務將會中斷而無法使用... 此時就是考慮IT是否用新備份的時候了,回復一台完整可供查詢的DNS Server將是服務回復的關鍵因素!
而另一個風險... 想像如果DNS server上面的紀錄(一般稱DNS record)被串改,則用戶可能就此連到別的網站去,如果被有心人士利用,則可以作為詐騙的工具...試想如果有人做了一個跟PXHome一樣的交易網站,在交易時候透過偽裝的程式就可以輕易的盜取使用者的交易或個人資料,甚至是信用卡資料,只要偽裝的網站長得一樣,一般人很難察覺... 即使有SSL加密的網站,也很難防範DNS Server被攻陷造成的傷害...



圖五、失守DNS Server示意圖


保護 DNS Server的方式


敝人在下不是網路之才,所學不深,目前了解到防範DNS server被攻擊的幾種情境,主要以DDoS最為麻煩(DNS Abuse Attack),而這些攻擊不外乎是利用大量的查詢來癱瘓DNS Server,有的神級Hacker甚至可以透過攻擊尋得漏洞侵入DNS Server... 而保護DNS server應當要做到:

  • 落實iptables的管理,非服務Port不開放,且DNS Server不要裝其他服務
  • 落實網路節點上的防火牆管理,此點同上,僅是層次上不同
  • 如不需服務大眾,盡可能改為內部存取ONLY (一般設定上可以限制存取網段,可配合iptables做設定)
  • 如不需要,請關閉any查詢 (所耗資源較大)
  • 做好DNS Cluster Group的設定 (避免掛一台而無法提供服務)

而說到保護,在好的保護不如做好完整的備份與還原機制,X戰警的金剛狼就是最好的例子...快速恢復的能力就是王道!能快速復原被攻陷的DNS Server,讓服務快速恢復營運,勝過做100種防護,而此點在目前的Cloud環境上將是最好的演示∼透過類似映象檔備份或是Image的備份,再快速生成主機,恢復服務,就不用再擔心被Hacker攻破啦∼ (PS: 漏洞還是要修啦@@) 這邊提供一個備份的策略給大家參考:

  • 日備份,以git為版本儲存體
  • 每次備份檢核前一份備份(版本)資料,透過diff做差異report
  • 差異部分通知管理者、管理者主管(交叉檢核)
  • 準備好還原機的映象檔及備機

保護用戶端 DNS Server被串改的方式


最後談到,保護用戶端的部份,我想最快的方式就是使用OpenDNS所提供的DNSCrypt工具,讓Client端跟DNS Server端建立私密通道,可保證(盡可能保證啦)中間的資料不被串改,因此,只要您所使用的DNS Server有實作此協定,可以安裝DNSCrypt試試看!

後記
上回文章我們從 gov.ph 網站安全性談起,從網站開發者的角色,從腳本語言的基本漏洞開始談起。這回我們與大家來談 DNS ,從 DNS 基本概念,到如何執行,最後講身為開發者需要注意 DNS 的哪些部分。最終最終大部分的漏洞,幾乎都是開發者的疏忽,只要多做判斷、多做保護,網站的安全性問題可以被降低許多。
MiCloud 內部也有提供 DNS 服務,給予外部、內部使用,MiCloud DNS 可以單獨申請使用,使用受信任、外部的服務,也是方法之一。
希望各位在開發、架構都能夠謹慎考量,注意到每一個細節,了解其中實作理論,讓網站開發更為完整、更為安全,避免掉無謂的安全性問題再度發生。網路上沒有絕對的安全,但是基礎的防範,是身為開發者應有的責任。

參考資料




如果你覺得文章對自己有幫助的話,歡迎點個讚 (like),加入 MiCloud Fans page ,最新的文章、討論與大家分享。

2013年5月13日 星期一

gov.ph 網站為例,網站攻擊與防範

gov.ph 網站為例,網站攻擊與防範



於昨天晚上看到網路上許多資料開始發佈 an 已經攻下菲律賓網站,大多是比較攻擊順利成功,或者是網站頁面被更改的方式。

對於網站部屬架設角色來說,我們正在思考,以後要如何避免掉類似的事情再度發生,以下幾個討論方向,

DDos 攻擊


在最開始,發現的攻擊手段,主要是由從 DDos 攻擊方式開始,剛開始由網友發起,用最土法的方式進行攻擊,

http://ptt4ck.ap01.aws.af.cm/

這個網頁的使用方式,十分簡單,主要是利用 AJAX 不斷發出 request 對於 input list 裡面列表的網站,不斷輪循進行『訪問』,而這個活動的確也引起第一波攻擊成功,有把幾個網站的確就這樣搞垮下來。

這個攻擊手段的確是最容易做到的方式,許多網站(尤其是政府網站),平常並沒有同時大量訪問(request)的機會,因此只要受到同時間 1000 以上訪問者的時候,就有可能造成網站癱瘓(505 Error)

DDos 防範


DDos 其實也是最常見的攻擊之一,當然防止方式可以從基本的建置,第一層首先在 apache 安裝類似 mod_dosevasive 模組,防止在單一 ip 底下同一時間大量進行 request ,將時間分散掉,降低 apache server concurrent.

另外一種方式是透過 nginx ,利用 nginx 的特性,建構 reverse proxy ,對應到多台不同的 web server,讓 web application 至少拖延死掉的時間。

建議的方式採用 load balancer ,對應到不同機器,當然就 load balancer 服務,如果採取硬體價格上是相對價格提高,對於中小型公司來說,可以參考
簡單的方式透過輪巡,當機器(web application server) 當機無回應的時候,對應到下一台機器上。

當然如果在架構上自己能夠在本地端(local)以及遠端 (remote),當本地機器過載,無法承受負擔時,搭配遠端機器配置 Cloud Service 進行 API 自動進行架構擴張,保持服務能夠正常運作。

語言漏洞攻擊


技高一籌,還是人為疏失,由 gov.ph 窺探 vim 疏忽 利用編輯器,編輯檔案後,因為編輯器本身會自動進行副本複製。

原本修改 test.php
卻會自動複製一個 test.php~ 檔案產生

當『有心』的瀏覽者將網址稍微修改,後面多加上一個 『~』 之後,程式碼就可以一覽無遺。

語言漏洞層面防範


當然上面的處置方式,網路上已經很快的有防範方式 如何避免像 gov.ph 的漏洞

類似的錯誤防範機制很多種,可以透過修改 apache, iis 的設定來防範類似問題,讓動態語言的程式碼不會輕易外露。

更簡單的方式,可以透過 .htaccess 來進行最簡單的設定,當然還有透過 framework 結合 ORM ,隱藏自己的設定檔案,防範外部取得 config setting.

程式佈署防範


當然也可以從 deploy 的流程來談,相信有許多網站還是透過 ftp 的方式來進行資料上傳佈署,當然這是方法之一,不過也會造成許多問題。

尤其是類似這種資料夾中不知道夾帶了什麼東西,這次佈署的檔案版本,檔案目前狀況。

另外可以透過 continue integration 的方式進行程式佈署,透過程式碼檢測、驗證、unit test 做到流程上的控管,確保每次佈署的程式錯誤率降到最低。

後記


這次針對 gov.ph 看到許多網站在程式以及架構上的問題,世界上沒有完美的網站,只有保持服務不中斷,將 down time 降到最低,盡量維持一致性的服務。

當然這當中還有很多開發人員的問題,例如 XSS, SQL injection 等隱藏問題在其中,不過這次主要以 gov.ph 為例,就沒有舉例太多額外的資訊,以這次的例子,思考如果問題發生在自己家裡的網站,要怎麼防範。

身為開發者,以及維護者都需要了解一件事情,『便宜行事背後的成本,未來將付出更大的代價。』

2013年5月4日 星期六

PHP 開發者轉換到 node.js 開發方向

Node.js for php develpers

從某一種語言跳到另外一種語言,通常來說痛感應該是不會太大,只要有些觀念釐清即可,畢竟每種語言存在都是有某些特別的道理,或者是有他的歷史存在意義,所以語言的對戰比較之類的事情,我對於這種事情通常是一笑至之。有時間去吵那些莫名其妙的事情,倒不如發揮自己所長,好好將產品快速產出,這才是『實現的王道』

話說回來,前面談到前端開發者來說 JavaScript 是一個很棒的利基點,也是一個很好出發點,轉向到後端開發當中。那是否意味著其他語言開發者就沒有相對的機會呢?

就個人在其他語言上琢磨並沒有這麼多, PHP 倒是寫過不少年,因此我從 PHP 開發者的角色來檢視一下,有哪些觀念需要被改變,需要被調整。

Node.js 是一個整體的服務 / 語言

對於 php 開發者來說,一開始的環境就是要先開始架設 Apache / Nginx,接著使用 cgi 的方式來起動 php ,當然在 linux 底下的話,直接使用套件管理,直接進行安裝會是更為方便。

apt-get install php apache

但是在 node.js 裡面,node 本身就是一個服務,不需要其他相關的程式進行啟動, node 本身就可以是一個後端的服務,或者一個 web service ,更或者是一個 command line 的進行,所以 node.js 是不需要任何相依設定。

也因為如此,所以許多 apache 幫你處理掉的事情,在 node 裡面都需要自己處理,這件事情聽起來或許很煩,事實上也是如此,開發 php 的時候許多事情 apache 都已經幫你處理完的事情,node.js 在 web 上,前面的所有開發都需要自己來,這是一個很大的不同,你需要稍微了解一下之前 apache 到底幫 php 做了哪些事情,接下來開發 node.js 才能夠了解,為什麼他要做這些事情。

Node.js 每個檔案都是獨立的 Class

node.js 每一個檔案都可以視為獨立的 Class ,這跟我們之前所認知的 JavaScript 似乎有很大的不同,JavaScript 本身都是採用 fuction call ,變數宣告也很容易互相影響,可是因為 Node.js 採用 CommonJS 標準,因此在每個程式裡面,變數都不會互相影響,每個檔案內的變數都是獨立的。

開發 php 的時候很經常會使用到 require,而 php 將會把這個檔案讀取進來,當然變數也會連帶的影響到,可能 a.php 的變數會出現在 b.php 裡面,這都是時常發生的事情。
a.php
<?php
$hello = 'abc';
?>

b.php
<?php
$hello = 'world';
?>

main.php
<?php
require('a.php');
require('b.php');
echo $hello;
// print 'world'
?>

範例如上面,當我們執行 main.php ,就會得到 world 這個資訊,可見 a.php, b.php 兩者的變數會互相干擾,同時 main.php 可以直接讀取已經宣告過的變數,這在多數的 php 開發者都有深刻的經驗,當然這也是一個特性,開發 php 的時候這個特性,是個很方便的東西。
在 node.js 開發裡面卻不是這麼回事,每個檔案都是獨立的 class,的程式都有不同的東西。

a.js
exports.hello = 'abc';

b.js
exports.hello = 'world';

main.js
a = require('./a.js');
b = require('./b.js');
console.log(a.hello);
// print 'abc'
console.log(b.hello);
// print 'world'

從上面的範例來看,在 node.js 開發上的確與 php 有許多不同,尤其是變數宣告處理上,更是不一樣的架構,這樣的好處 node 不會有變數互相打架的狀況發生,當然麻煩的部份也是,無法共用變數,思維上的確與 php 原有的宣告思維上有許多不同。

Node.js 的套件都存在於 NPM 上

php 開發的時候大多數時間我們的環境都已經把所有需要的套件安裝上去了,或者是需要憑靠著經驗,從 log 中查看到底還缺少哪些套件,當然 php 之前有 pear 這樣的東西可以進行套件安裝,不過對於 pear 的社群維護度來說,通常我還是在一開始架設 apache 的時候就先把所有的套件全部設定完畢。

在 node.js 裡面,套件相依性,以及套件管理是很重要的一環, npm 就是如此的東西,可以透過 npm 進行 node.js 套件的安裝,例如我們常用的 express

npm install express@2.5.8

可以透過指令去尋找,安裝,解除,更可以透過指令來指定版本號碼,特別是每個 node.js 專案幾乎都需要重新安裝一次套件,這個部分對於 php 開發者是覺得神奇,而且浪費空間的事情。

不過仔細想想,開發專案,在不同時期,不同時間點,我們需要的 module 可能也會不同,因此在每個專案裡面安裝套件似乎又如此的合情合理,當然還是必須要說,這樣子是真的比較佔用空間,不過又如何,目前的硬碟這麼大,對於開發者來說,裝 code 的空間佔用多少?

因此每個 php 開發者轉移到 node.js 時候,需要去了解、熟悉 npm 這個指令。

Node.js 的 package.json 設定是必要的

如上面所提到,每個 node.js 專案都是需要去被執行 npm ,進行相依模組的安裝。接下來你將開發許多不同的 node.js 專案,請先做好相依模組記錄的習慣,在每個專案目錄底下設定 package.json ,設定好版本號。

cd project_name
npm install

接著開發、維護的成員,可以不用再去猜測之前的模組為哪個版本,直接透過你之前設定的 package.json ,透過 npm 進行快速的安裝,立即進入開發的行列之中。

Node.js 是 Event driven I/O 處理

對於 php 開發者來說,開發程式的習慣就是很直覺性的 debug,設定 break point ,觀看 log 跳到的地點,程式的執行是依序的,由上往下依序執行,以前我們的老師也都是這樣子教導我們的,程式的確也是這樣看的,

$my_file = 'file1.txt';
$handle = fopen($my_file, 'r');
$data = fread($handle,filesize($my_file));

$my_file = 'file2.txt';
$handle = fopen($my_file, 'r');
$data = fread($handle,filesize($my_file));

但是,在 node.js 開發裡面,事情似乎變得不一樣,我們的開發寫法開始有了許多改變,event-driven 是一個很強的衝擊,許多的東西都使用 callback 都使用匿名函式來銜接,當然連同裡面的變數也是如此,而這些變數的來源,通常都要去參考 nodejs.org/api 的部份,事情是需要不斷的在 callback 裡面慢慢被完成,這的確很奇怪,也的確很神奇,

var fs = require('fs');
var my_file = 'file1.txt';
var data;

fs.readFile(my_file, 'utf8', function (err, data) {
    data += this.data;
    my_file = 'file2.txt';
    fs.readFile(my_file, 'utf8', function (err, data) {
        data += this.data;
    });
});

如同之前的 php 程式,讀取兩個不同檔案的程式架構卻全然不同,在 node.js 裡面許多程式都是以非同步的方式執行,你無法依照以前排序的方式進行開發,當然程式的執行順序也不會如你所願,如果希望讀取檔案完成之後,進行另外一個檔案的讀取,那就只能進去 callback 裡面,進行另外一段程式的進行。

聽起來似乎非常奇怪,不過這就是 JavaScript ,這就是 node.js ,這是他獨特之處,如果希望開發 node.js 就請習慣這種風格,也請習慣 event-driven 的方式。程式只會等到被執行的時間點才會進行,程式執行的時間並不會依序進行。

後記

就在你看這篇文章的時候,表示你對於 node.js 應該是有聽過,或者是有想要進入這個領域,想看看 node.js 到底要怎麼開發,當然這是一個好的開始,表示你期待改變。

這邊很尊重你想要改變的心情,如果你是要拿來測試新的專案、新的服務、甚至於公司目前有改造計畫,這是一個不錯的發想開始。不過,如果你的程式已經有了許多基礎建設、許多歷史的累積,這邊不建議妳採用新的語言進行開發,也不建議妳整個重新打掉這個『正在運作的服務』。

node.js 是不是很不穩定? node.js 是不是適用於我的開發架構? node.js 到底能不能開發大型架構? 如果有開發者問我這樣的問題,我通常會回答他,先使用 node.js 想辦法建立一個 todo list, 留言板之類的簡單網站,之後,我們再來討論。

程式語言只是一種實現的工具,每個階段都會有不斷的程式架構調整,程式只有更好,沒有最好,不斷的調教,不斷的改善,當每段程式上線我們舉杯慶祝的同時,下一秒,開發人員又回到座位上繼續進行下一個里程碑,『程式只有更好,沒有最好』

本文章原文:

  • http://blogger.micloud.tw/
  • http://ithelp.ithome.com.tw/question/10119996?referr=jsdc