Xây dựng hệ thống ngăn chặn tấn công từ chối dịch vụ

Một phần của tài liệu Xây dựng giải pháp chống tấn công từ chối dịch vụ trên tầng ứng dụng cho websites (Trang 32)

2.2.1. Lựa chọn công nghệ.

Với các chức năng cần thiết của hệ thống như đã nói ở trên cộng với thời gian giới hạn tác giả lựa chọn một proxy mã nguồn mở là nginx. Nginx là một proxy mã nguồn mở với cộng đồng rất lớn khả năng mở rộng cũng như cấu hình rất đơn giản. Ta có thể viết thêm module với nhiều ngôn ngữ khác nhau như c, perl, lua. Các đặc điểm nổi trội của nginx là:

- Xử lý các file tĩnh và file index, tự động đánh index

- Tăng tốc reverse proxy với việc caching, cân bằng tải (load banlancing), khả năng chịu lỗi (fault tolerance)

- Hỗ trợ tăng tốc caching với FastCGI, SCGI, uwsgi

- Giới hạn số kết nối, yêu cầu từ một địa chỉ IP

- Kiểm soát truy cập bởi: địa chỉ IP, mật khẩu (HTTP basic authentication) và từ các yêu cầu con (subrequest)

Khi muốn thêm các tính năng nào đó ta có thể viết thêm module mới rất dễ dàng theo ý muốn. Thêm vào đó do đặc điểm là mã nguồn mởi nên nginx cũng có rất nhiều các bản khác nhau được các nhà phát triển khác phát triển thêm dựa trên mã nguồn gốc với nhiều đặc điểm tốt hơn. Các module của nginx ban đầu có thể viết bằng c hoặc perl, các module viết bằng c thông thường sẽ chạy rất nhanh nhưng khó viết còn các module viết bằng perl thì dễ viết hơn rất nhiều nhưng tốc độ chạy chậm. Sau khi nghiêm cứu toàn bộ các phiên bản khác nhau được phát triển từ nginx tác giả lựa chọn openresty là phiên bản được dùng để phát triển hệ thống chống tấn công từ chối dịch vụ của mình.

Openresty là một phiên bản được phát triển từ nginx, phiên bản này hỗ trợ rất mạnh việt viết module bằng ngôn ngữ cấp cao lua. Hỗ trợ chạy luajit để đảm bảo tốc dộ gần tương đương với các module viết bằng c. Hỗ trợ rất nhiều thư viện cũng như function ngay từ đầu để ta các thể phát triển thêm vào các chức năng như ý muốn. Thêm vào đó openresty được phân phối hoàn toàn miễn phí cộng với cộng đồng người dùng và phát triển tương đối lớn nên khi phát triển hệ thống chống tấn công từ chối dịch vụ sẽ không gặp phải trở ngại về mặt kỹ thuật lớn nào. Với những đặc điểm như trên thì openresty chính là công nghệ rất phù hợp để có thể phát triển được hệ thống với nhiều tính năng, khả năng mở rộng, khả năng đáp ứng nhất có thể.

2.2.2. Xây dựng các thành phần của hệ thống.2.2.2.1. Cài đặt môi trường. 2.2.2.1. Cài đặt môi trường.

Do yêu cầu về chịu tải cũng như việc tương thích với mã nguồn của openresty nên môi trường dùng để chạy hệ thống chống tấn công từ chối dịch vụ sẽ là linux. Sau khi tham khảo rất nhiều phiên bản linux khác nhau tác giả chọn phiên bản centos 6 là một phiên bản được dùng rộng rãi và rất ổn định trong thời điểm hiện tại. Centos được hỗ trợ từ cộng đồng rất lớn và được chạy trên nhiều hệ thống lớn nên khi đưa hệ thống ra chạy thực tế sẽ không gặp phải các lỗi không lường

trước được. Thêm vào đó centos các thư viện gần như đã có sẵn lên sẽ không mất thời gian cho việc cài đặt thư viện cũng như các thành phần cần thiết. Như đã nói ở trên hệ thống sẽ được xây dựng trên nền openresty và ngôn ngữ để lập trình sẽ là lua.

Cài đặt openresty:

#cài đặt repo của epel

rpm -ivh https://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm

#cập nhật gói yum update

#cài đặt các gói cần thiết để biên dịch

yum install readline-devel pcre-devel openssl-devel gcc perl wget #download openresty wget https://openresty.org/download/openresty-1.11.2.1.tar.gz #giải nén và biên dịch tar -xvf openresty-1.11.2.1.tar.gz cd openresty-1.11.2.1 ./configure make make install

#openresty được cài vào thư mục /usr/local/openresty

Cài đặt các thư viện lua cần thiết để phát triển hệ thống:

#cài dặt gói cần thiết

yum install git lua-devel unzip #cài đặt luarocks

git clone git://github.com/keplerproject/luarocks.git ./configure

make build make install

#cài đặt các gói cần thiết cho các module

luarocks install luasec OPENSSL_LIBDIR=/usr/lib64/ luarocks install lua-cjson

luarocks install luasocket

#các thư viện sẽ dược cài vào thư mục /usr/local/lib/lua/5.1 #lấy các thư viện cần thiết để phát triển

git clone https://github.com/openresty/lua-resty-limit-traffic

git clone https://github.com/openresty/lua-resty-cookie

git clone https://github.com/openresty/lua-resty-string

git clone https://github.com/hamishforbes/lua-resty-iputils

2.2.2.2. Module tạo cookie xác thực.

Phần quan trọng nhất của module xác thực người dùng là phần tạo cookie xác thực như các yêu cầu đã nói ở phần 2.1.1. Phần cookie xác thực người dùng trong hệ thống sẽ được xây dựng bằng cách:

Bước 1: lấy thời gian hiện tại của hệ thống sau đó chia lấy phần nguyên với một khoảng thời gian xác định gọi là thời gian hợp lệ của cookie.

Bước 2: lấy các giá trị đặc trưng của người dùng ở đây là địa chỉ ip và useragent của request.

Bước 3: Cộng một chuỗi secret mà chỉ server mới có với hai thông tin lấy được ở bước 1 và bước 2 sau đó dùng mã hoá băm với dữ liệu này. Cookie authen cuối cùng sẽ là một chuỗi có độ dài bằng độ dài của thuật toán băm tương ứng. Thuật toán này được triển ra ra code như sau.

local current_time = os.time()

local authen_data = ngx.var.remote_addr .. useragent

local secret = authen_data .. current_time - (current_time % cookie_windows) local sha256 = resty_sha256:new()

sha256:update(key) sha256:update(secret)

local digest = str.to_hex(sha256:final())

Phần này dùng thư viện lua-resty-string của openresty. Trong đó key là chuỗi bí mật chỉ có server có. Cookie xác thực này có những đặc điểm phù hợp với yêu cầu đã được trình bày như:

- Gần như không thể giả được cookie xác thực trừ khi biết được chuỗi bít mật của server.

- Do dùng mã hoá băm nên người tấn công cũng khó có thể đoán được các yếu tố nào dùng để xác thực.

- Cookie chỉ được xác thực trong một khoảng thời gian xác định nên tránh được việc người tấn công dùng mã giả trình duyệt để lấy cookie sau đó dùng cookie này cho các request tấn công từ chối dịch vụ sau.

- Mã hoá băm sha256 có mức độ an toàn tương đối tốt và thời gian chạy cũng như tài nguyên yêu cầu tương đối thấp nên rất hợp cho một hệ thống chống tấn công từ chối dịch vụ như này.

Xác thực tính chính xác của cookie xác thực của người dùng có:

Phần này rất đơn giản là chỉ lấy cookie xác thực của người dùng nếu có sau đó so sánh với cookie xác thực mà server tạo ra cho người dùng. Phần này được viết dùng thư viện lua-resty-cookie của openresty với mã như sau:

--- lấy cookie xác thực, nếu không có thì cookie sẽ có giá trị là nil ( None hoặc rỗng)

local ck = require "resty.cookie" local cookie, err = ck:new() if not cookie then

ngx.log(ngx.ERR, err) return ngx.exit(500) end

local ecofair_cookie, err = cookie:get(ecofair_cookie_name) --- xác thực xem cookie có chính xác không

if (not ecofair_cookie or not(ecofair_cookie == digest)) then … tạo cookie xác thực cho người dùng với module thích hợp

2.2.2.3. Module xác thực người dùng bằng javascript.

Module này làm tương đối đơn giản do yêu cầu cần chạy được với tất cả các trình duyệt phổ biến và người dùng dùng. Chức năng của module rất đơn giản là tạo cookie cho người dùng và yêu cầu trình duyệt tải lại trang web với đường dẫn đang xem. Phần này được triển khai ở mực rất đơn giản và sẽ được phát triển trong tương lai với nhiều tính năng hơn như xác thực browser dựa vào javascript, dùng một số kỹ thuật javascript để phát hiện website đang được tải bời các công cụ bô phỏng trình duyệt access_list:incr(authen_data, 1) ngx.say(string.format("<html><body><script> document.cookie=\"%s=%s\";window.location.reload(true);</script></body></html >", ecofair_cookie_name, digest)) ngx.exit(ngx.HTTP_OK) với mã rất đơn giản là

<html><body><script>document.cookie="Cookie xác thực";window.location.reload(true);</script></body></html>

document.cookie="Cookie xác thực"; là phần tạo cookie cho người dùng và window.location.reload(true); để trình duyệt tự tải lại trang.

2.2.2.4. Module xác thực bằng captcha.

Module này được triển khai dùng dịch vụ recaptcha của google để tạo tính đơn giản. Trong phần này xử dụng hai thư viện của lua để viết lại phần xác thực captcha với phía server của người dùng là lua-cjson và luasec. Phần tạo captcha cho người dùng rất đơn giản bằng mã html như sau:

<html> <head>

<title>Ecofair</title>

<script src="https://www.google.com/recaptcha/api.js" async defer></script> </head>

<body>

<form action="/cgi-bin/ecofair-captcha" method="GET"> <div class="g-recaptcha" data-sitekey="site’s key"></div> <br/>

<input type="submit" value="Submit">

</form> </body> </html>

Trong đó site’s key là mã được google cung cấp cho người dùng khi đăng ký dịch vụ recaptcha của google.

Module xác thực này do dùng version mới hơn của recaptcha và chưa có thư viện nào của lua thực hiện xác thực với google nên tác giả tự viết phần xác thực với phía server của google xem phần captcha nhập vào có hợp lệ không.

function verify_captcha(g_recaptcha_response) local https = require 'ssl.https'

local cjson = require 'cjson'

--- -- https://www.google.com/recaptcha/api/siteverify

-- secret Required. The shared key between your site and ReCAPTCHA.

-- response Required. The user response token provided by the reCAPTCHA to the user and provided to your site on.

-- remoteip Optional. The user's IP address.

---

local recaptcha_url = "https://www.google.com/recaptcha/api/siteverify" local body, code, headers, status = https.request(recaptcha_url, "secret=" .. recaptcha_secret .. "&response=" .. g_recaptcha_response)

local data = cjson.decode(body)

--- -- {

-- "success": true|false,

-- "challenge_ts": timestamp, // timestamp of the challenge load (ISO format yyyy-MM-dd'T'HH:mm:ssZZ)

-- "hostname": string, // the hostname of the site where the reCAPTCHA was solved -- "error-codes": [...] // optional -- } --- if (data['success']) then return true end return false end 30

Khi người dùng giải thành công captcha và submit lại lên thì sẽ tạo cookie xác thực cho người dùng thông qua header của kết quả trả về dùng module lua-resty-cookie của openresty.

local ok, err = cookie:set({

key = ecofair_cookie_name, value = digest })

2.2.2.5. Module xác thực bot của các công cụ tìm kiếm.

Như đã nói ở chương 1 có 2 cách xác thực bot của công cụ tìm kiếm khác nhau. Tuy vào khi nghiên cứu các yêu cầu đối với trang thương mại điện tử cũng như các công cụ tìm kiếm phổ biến nhất thì các công cụ hay được người dùng dùng nhất là google, bing của microsoft và củ facebook. Do đó phòng phần này triển khai thuật toán xác thực bot tìm kiếm bằng dns và áp dụng với 2 công cụ tìm kiếm là google và bing và xác thực bằng ip với facebook. Module xác thực qua dns dùng thư viện luasocket của lua và được cài đặt thông qua luarocks. Module xác thực qua ip dùng module lua-resty-iputils. Với code rất đơn giản như sau:

Xác thực googlebot

if ngx.re.match(useragent, "googlebot", "i") then -- ngx.say("googlebot")

local socket = require('socket')

google_hostname = socket.dns.tohostname(ngx.var.remote_addr) -- test --

-- google_hostname = socket.dns.tohostname("66.249.66.1") -- ngx.say(google_hostname)

-- test --

if (not google_hostname or not ngx.re.match(google_hostname, "googlebot.com")) then ngx.exit(ngx.HTTP_FORBIDDEN) -- captcha authen end return end Xác thực bingbot --- -- bing's bot authentication --

-- https://udger.com/resources/ua-list/bot-detail?bot=bingbot ---

if ngx.re.match(useragent, "http://www.bing.com/bingbot.htm") then local socket = require("socket")

---

-- https://www.bing.com/webmaster/help/which-crawlers-does-bing-use- 8c184ec0

---

bing_hostname = socket.dns.tohostname(ngx.var.remote_addr)

if (not bing_hostname or not ngx.re.match(bing_hostname, "search.msn.com")) then ngx.exit(ngx.HTTP_FORBIDDEN) end return end Xác thực facebookbot

local iputils = require("resty.iputils") iputils.enable_lrucache() --

local facebook_ips = { … facebook’s ip ranges … }

if ngx.re.match(useragent, "facebookexternalhit") or ngx.re.match(useragent, "Facebot") then

local iputils = require("resty.iputils")

if not iputils.ip_in_cidrs(ngx.var.remote_addr, facebook_whitelist) then return ngx.exit(ngx.HTTP_FORBIDDEN)

end return end

Khi bot không được xác thực sẽ trả lại người dùng cấm truy cập và dừng không cho request vào website nữa.

2.2.2.6. Module giới hạn số request của người dùng.

Như đã nói để hạn chế việc người tấn công dùng cách tạo cookie xác thực rồi dùng cookie đó để tấn công tiếp và thông thường khi tấn công từ chối dịch vụ thì người tấn công thường phải tạo số request nhiều nhất có thể. Thêm vào đó người dùng bình thường thường không tạo quá nhiều request trong một khoảng thời gian ngắn. Module này được xây dựng dựa trên thư viện lua-resty-limit-traffic của

openresty. Khi người dùng vượt quá giới hạn đặt ra thì bắt buộc phải bị xác thực bằng captcha.

local limit_req = require "resty.limit.req"

local lim, err = limit_req.new("ecofair_limit_req", 40, 10) if not lim then

ngx.log(ngx.ERR, "failed to instantiate a resty.limit.req object: ", err) return ngx.exit(500)

end

local key = ngx.var.binary_remote_addr .. useragent local delay, err = lim:incoming(key, true)

if not delay then

if err == "rejected" then

local authen_data = ngx.var.remote_addr .. useragent access_list:safe_set(authen_data, 6)

else

ngx.log(ngx.ERR, "failed to limit req: ", err) return ngx.exit(500)

end end

2.2.3. Triển khai hệ thống thực tế.

Hệ thống được triển khai dựa trên openresty bằng cách cấu hình openresty cho phù hợp với yêu cầu. Các files cấu hình và mã nguồn được thêm vào như sau:

nginx.conf: file cấu hình chung của openresty như khi request được cho phép thì sẽ chuyển đến đâu, cần tải các thành phần hay thư viện nào để chạy code.

captcha.html: file chứa phần mã để hiện captcha cho người dùng, có thể sửa

Một phần của tài liệu Xây dựng giải pháp chống tấn công từ chối dịch vụ trên tầng ứng dụng cho websites (Trang 32)

Tải bản đầy đủ (PDF)

(60 trang)