Nhận gúi tin trong IP-Crypto

Một phần của tài liệu đề tài phần mềm bảo mật mạng dùng giao thức ip quyển 4a các phần mềm bảo mật gói ip trên hệ điều hành linux (Trang 120 - 126)

Trong Linux để đăng ký một giao thức mạng nào đú chỳng ta sử dụng hàm

inet_add_protocol(). Khi gọi hàm này thỡ trong nhõn Linux được thờm vào cấu trỳc dựng để xử lý loại gúi tin cú giao thức mạng cụ thể nào đú. Trong trỡnh của

chỳng ta gúi tin được bảo mật đú chớnh là gúi tin cú giao thức là IPPROTO_ESP. Những gúi tin bảo mật đó được hàm ipsec_tunnel_start_xmit( ) xử lý và gỏn cho

giao thức gúi tin là IPPROTO_ESP. Và ở bờn nhận chỉ cú những gúi tin nào cú giao thức là IPPROTO_ESP mới được trỡnh ipsec xử lý.

Trong hàm ipsec_rcv.c cấu trỳc struct inet_protocol esp được xỏc định như sau:

struct inet_protocol esp_protocol = {

ipsec_rcv, /* ESP handler */ NULL, /* TUNNEL error control */

0, /* next */ IPPROTO_ESP, /* protocol ID */ 0, /* copy */ NULL, /* data */ "ESP" /* name */ };

Và trong hàm ipsec_init() trong tệp ipsec_init.c thực hiện việc đăng ký giao thức bằng cỏch gọi hàm:

inet_add_protocol(&esp_protocol);

Trong cấu trỳc esp trờn thỡ ipsec_rcv là hàm dựng để nhận và xử lý gúi tin, và IPPROTO_ESP chớnh là giao thức của gúi tin. Như vậy, với cỏc gúi tin bảo mật của chỳng ta thỡ giao thức của gúi tin bao giờ cũng là IPPROTO_ESP. Và gúi tin cú giao thức IPPROTO_ESP sẽ được hàm ipsec_rcv() nhận và xử lý. Việc quan

trọng nhất của chỳng ta đú chớnh là việc lựa chọn cỏch xử lý gúi tin phự hợp nhất trong hàm ipsec_rcv().

Hàm ipsec_rcv(struct sk_buff *skb, unsigned short xlen) được dựng để xử lý gúi tin IPPROT_ESP nhận về. Cỏc cụng việc cần thực hiện trong hàm ipsec_rcv() đối với gúi tin bảo mật đú chớnh là việc xỏc thực gúi tin, tỡm kiếm bộ tham số tương

ứng với gúi tin, giải mó, loại bỏ phần dữ liệu chẵn khối, loại bỏ phần IP header

thờm vào (nếu trong trường hợp tunnel mode) . . . và chuyển gúi tin cho tầng mạng cao hơn để xử lý. Trong hàm ipsec_rcv (), bởi vỡ bộ tham số an tồn cho

connection cố định là hàm Mó khối MK1 và hàm băm MD5 nờn trong chương

trỡnh chỳng ta sẽ lựa chọn 2 hàm này để tăng tốc về thời gian.

Việc đầu tiờn trong hàm ipsec_rcv() thực hiện chớnh là việc xỏc định giao thức của gúi tin. Nếu gúi tin cú giao thức khụng phải là IPPROTO_ESP thỡ chương trỡnh sẽ bỏ qua khụng xử lý gúi tin này:

protoc = ((struct iphdr *)skb->data)->protocol; if(protoc != IPPROTO_ESP) {

}

Sau khi xỏc định được gúi tin cú giao thức là IPPROTO_ESP thỡ chương trỡnh

thực hiện việc lấy bộ tham số an toàn ứng với gúi tin thụng qua cỏc tham số từ gúi tin mang tải như cii, địa chỉ nguồn của gúi tin và giao thức. Việc chứa đựng tham số cii là rất quan trọng trong gúi tin bảo mật. Bởi vỡ, trờn một cặp mỏy gateway cú thể dựng để bảo vệ nhiều cặp mạng con ảo khỏc nhau. Mà do yờu cầu thực tế mỗi mạng con lại cú bộ tham số an toàn khỏc nhau. Vỡ thế, đối với gúi tin đến trong trường hợp tunnel thỡ khụng cú cỏch gỡ khỏc hơn là chỳng ta phải dựa vào chỉ số cii để biết được gúi tin cần phải được dựng bộ tham số an toàn cho connection cụ thể nào trong cỏc bộ tham số an toàn cho cỏc connection hiện tại đang cú trờn mỏy gateway.

cnid.dst.s_addr = ipp->daddr; /* Lấy địa chỉ nguồn của gúi tin */ switch(proto) {

case IPPROTO_ESP:

espp = (struct esp *)(skb->data + iphlen);

cnid.cii = espp->esp_cii; /* Lấy thụng số cii của gúi tin*/ break;

ciid.proto = proto; /* Xỏc định giao thức tương ứng */

Hàm lấy bộ tham số an toàn tương ứng với connection:

spin_lock_irqsave(&tdb_lock, tdb_flags); tdbp = gettdb(&cnid);

Nếu khụng tỡm thấy bộ tham số an toàn cho gúi tin thỡ gúi tin sẽ bị bỏ qua khụng xử lý: if (tdbp == NULL) { . . . if(stats) { stats->rx_dropped++; } goto rcvleave; }

Khi tỡm thấy bộ tham số an toàn tương ứng với connection hiện tại. Chương trỡnh sẽ thực hiện việc kiểm tra chuỗi số của gúi tin xem liệu gúi tin đú cú bị gửi lặp lại hay là đó quỏ cũ hay khụng nhờ hàm ipsec_checkreplaywindow(), nếu gúi tin bị lặp hoặc đó quỏ cũ thỡ gúi tin bị bỏ qua:

if (!ipsec_checkreplaywindow(tdbp, replay)) { . . .

if(stats) {

stats->rx_dropped++; }

goto rcvleave; }

Chương trỡnh sẽ thực hiện tớnh toỏn dữ liệu xỏc thực trờn gúi tin. Nếu phần dữ liệu xỏc thực tớnh được mà khụng so khớp với phần dữ liệu xỏc thực mà gúi tin mang tải điều đú cú nghĩa là nội dung gúi tin đó bị thay đổi. Gúi tin sẽ khụng được xử lý: Lệnh lấy dữ liệu xỏc thực mang tải trờn gúi tin:

authenticator = &(dat[len - authlen]);

Đoạn trỡnh tớnh toỏn dữ liệu xỏc thực trờn gúi tin:

if(tdbp->tdb_authalg) {

switch(tdbp->tdb_authalg) { case AH_MD5:

tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->ictx; if(proto == IPPROTO_ESP) {

MD5Update(&tctx.md5, (caddr_t)espp, ilen); }

MD5Final(hash, &tctx.md5);

tctx.md5 = ((struct md5_ctx*)(tdbp->tdb_key_a))->octx; MD5Update(&tctx.md5, hash, AHMD596_ALEN);

MD5Final(hash, &tctx.md5); break;

}

Việc so sỏnh dữ liệu xỏc thực mang tải và dữ liệu xỏc thực tớnh được được thực hiện nhờ hàm so sỏnh memcmp():

if (memcmp(hash, authenticator, authlen)) { if(stats) { stats->rx_dropped++; } tdbp->tdb_auth_errs += 1; goto rcvleave; } else {

KNMS_PRINT(debug_rcv, "knms_debug:ipsec_rcv: authentication successful.\n");

}

Hàm ipsec_rcv() sau khi đó kiểm tra tớnh trung thực của nội dung gúi tin mang tải, sẽ thực hiện việc giải mó để lấy lại nội dung gúi tin nguyờn bản ban đầu bằng việc gọi hàm blockcipher_cbc_encrypt():

blockcipher_cbc_encrypt(idat, idat, ilen,

tdbp->tdb_key_e,(caddr_t)iv, 0);

Ở bờn gửi đó thực hiện việc thờm dữ liệu cho chẵn khối mó hoỏ. Thỡ ở bờn nhận

chỳng ta cần phải loại bỏ phần dữ liệu thờm vào này. Lệnh xỏc định độ dài phần dữ liệu thờm vào:

padlen = idat[ilen - 2];

Chỳng ta thực hiện việc kiểm tra xem dữ liệu được thờm vào cú phải theo thứ tự tuần tự 1, 2, 3, ... hay khụng? Nếu khụng phải thỡ đó cú lỗi xảy ra và gúi tin bị bỏ qua:

for (i = 1; i <= padlen; i++) { . . .

if(i != idat[ilen - 2 - padlen + i - 1]) { . . .

tdbp->tdb_encpad_errs += 1; }

}

Bởi vỡ gúi tin nguyờn dạng ban đầu khụng cú phần ESP header nờn khi chỳng ta thờm phần ESP header ở đầu gúi tin ở bờn gửi thỡ ở bờn nhận cũng phải thực hiện loại bỏ phần này đi. Trong Linux việc loại bỏ khoảng dữ liệu ở phần đầu gúi tin sẽ

được thực hiện với hàm skb_pull():

skb_pull(skb, esphlen);

Phần dữ liệu thờm vào ở cuối gúi tin sẽ được loại bỏ bằng hàm skb_trim():

skb_trim(skb, len - esphlen - pad);

Trong trường hợp giữa hai gateway bảo mật cú thiết lập đường hầm (tunnel) thỡ

phần IP header thờm vào cũng sẽ được loại bỏ:

if(ipp->protocol == IPPROTO_IPIP) { if(skb->len < iphlen) {

. . .

goto rcvleave; }

skb_pull(skb, iphlen); /* Hàm loại bỏ phần IP header */ ipp = (struct iphdr *)skb->nh.raw = skb->data;

skb->h.raw = skb->nh.raw + (skb->nh.iph->ihl << 2);

Sau khi khụi phục lại dạng gúi tin nguyờn bản ban đầu thỡ hàm ipsec_rcv() sẽ thực hiện việc gọi hàm netif_rx() để chuyển phần buffer dữ liệu lờn cho tầng giao thức trờn xử lý:

netif_rx(skb);

Gúi tin sẽ được đưa lờn ở tầng IP, sau đú sẽ được nhõn Linux tỡm kiếm đường đi tiếp theo của gúi tin trong bảng dẫn đường (routing table) và sau đú gúi tin được

gửi tới đớch (Quỏ trỡnh này gúi tin được đưa về dạng nguyờn bản ban đầu, khụng cú mó hoỏ).

Ch−ơng 2

Một phần của tài liệu đề tài phần mềm bảo mật mạng dùng giao thức ip quyển 4a các phần mềm bảo mật gói ip trên hệ điều hành linux (Trang 120 - 126)