2012-07-10 47 views
7

Tôi đang viết Mô-đun hạt nhân sử dụng các móc nối Netfilter để sửa đổi một số thông tin tiêu đề TCP và rõ ràng, trước khi gửi, tôi muốn tính lại tổng kiểm tra.
Tôi cũng chỉnh sửa tiêu đề ở phía bên nhận, vì vậy tôi cũng cần phải tính toán lại nó ở đó.Cách tính tổng kiểm tra TCP

Tìm kiếm trực tuyến, tôi thấy một số người nói rằng tôi có thể đơn giản đặt thành 0 và nó sẽ được tính toán cho tôi, dường như điều đó không hiệu quả.
Tôi cũng đã tìm thấy chức năng này

tcp_v4_send_check(struct sock *sk, struct sk_buff *skb); 

Mặc dù không ai giải thích cách này được sử dụng, và cho dù tôi thực sự có thể sử dụng nó ở việc tiếp nhận/gửi theo cùng một cách.
Nỗ lực của riêng tôi là đặt tổng kiểm tra thành 0 rồi gọi chức năng này qua skb tôi có và skb-> sk tôi có, vẫn không có gì.

Vì vậy, cách đơn giản để tính tổng kiểm tra dữ liệu TCP là gì?

+0

gì Chính xác thì bạn thiết lập để 0 và nơi mà bạn đã mong đợi để tìm ra checksum? Nhìn vào mã, bạn nên đặt tcp_hdr (skb) -> check to 0, sau đó gọi hàm và sau đó checksum mới sẽ ở trong đó. – BjoernD

+0

và đó là chính xác những gì tôi đã làm, nhưng tất cả các kết nối TCP chỉ đơn giản là không hoạt động khi tôi nạp các mô-đun. – Fingolfin

+0

Có lẽ bạn nên thêm thẻ 'C' vào câu hỏi. Btw, hãy xem http://www.winpcap.org/pipermail/winpcap-users/2007-July/001984.html – Jite

Trả lời

3

Để tính lại tổng kiểm tra, bạn nên tính toán tổng kiểm tra gia tăng - chỉ cần sửa đổi tổng kiểm tra hiện có dựa trên các trường bạn đã thay đổi, thay vì đọc toàn bộ gói.

Điều này phải được thực hiện trong khi bạn thay đổi gói, khi bạn biết cả giá trị cũ và giá trị mới bạn lưu trữ.

Ý tưởng cơ bản là tcp->check += (new_val - old_val).
Hơi phức tạp hơn một chút, vì:
1. old_valnew_val cần phải là giá trị 16 bit, được căn chỉnh trên 2 byte (ví dụ: thay đổi số cổng).
2. Việc kiểm tra sử dụng các số học bổ sung, vì vậy bạn cần phải làm "mang theo phản hồi". Điều này về cơ bản có nghĩa là, nếu tcp->check + new_val - old_val là số âm, bạn cần phải trừ 1 từ kết quả.

+1

Đây là cách làm đúng. Nó nhanh hơn và ít có nguy cơ bị hỏng dữ liệu hơn. Recomputing checksum từ đầu sẽ có nguy cơ che giấu bất kỳ tham nhũng đã xảy ra với dữ liệu. – kasperd

1

Dưới đây là một ví dụ trong đó kết hợp netfilter API + checksum cho TCP (không chỉ IP):

http://www.linuxvirtualserver.org/software/tcpsp/index.html

Nhìn vào tập tin gọi là tcpsp_core.c.

th->check = 0; 
    th->check = csum_tcpudp_magic(iph->saddr, iph->daddr, 
            datalen, iph->protocol, 
            csum_partial((char *)th, datalen, 0)); 
    skb->ip_summed = CHECKSUM_UNNECESSARY; 

(chú ý nó được chỉ định bằng không, kiểm tra trước, sau đó kiểm tra IP được chỉ định là không cần thiết).

Phụ thuộc vào đó netfilter mô-đun u tải (có rất nhiều !!!) họ sẽ làm việc ở lớp khác nhau, ví dụ, iptable làm việc tại lớp IP được hiển thị dưới đây (hình ảnh):

http://ars.sciencedirect.com/content/image/1-s2.0-S1389128608004040-gr3.jpg

1

@ Câu trả lời của ugoren là không chính xác. Theo RFC1624 https://tools.ietf.org/html/rfc1624, điều này đôi khi sẽ tạo ra -0 (0xFFFF), điều này không được phép.

Cách đúng để tính toán checksum nên là: new_tcp_check = ~(~old_tcp_check + ~old_val + new_val)

Các vấn đề liên quan