2012-07-10 76 views
7

私は、Netfilterフックを使ってTCPヘッダー情報の一部を変更するカーネルモジュールを作成しています。送信する前に、チェックサムを再計算します。
また、受信側でヘッダーを編集するので、そこでも再計算する必要があります。TCPチェックサムの計算方法

オンラインで検索すると、私は単純に0に設定すると、計算されてしまいます。明らかに動作しませんでした。誰もが、これはどのように使われるかについて説明していない、と私は実際には同じ方法で送信/受信でそれを使用できるかどうかけれども
私もこの機能

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

を見つけました。
私自身の試みは、チェックサムを0に設定して、私が持っているskbと私が持っているskb-> skを渡してこの関数を呼び出すことでした。

したがって、TCPデータグラムのチェックサムを計算する簡単な方法は何ですか。

+0

何をあなたは0に設定されなかったし、どこでチェックサムを見つけることを期待しましたか?コードを調べるには、tcp_hdr(skb) - > checkを0に設定してから関数を呼び出し、その後に新しいチェックサムがそこにあるはずです。 – BjoernD

+0

それはまさに私がやったことですが、モジュールをロードするとすべてのTCP接続が単純に機能しませんでした。 – Fingolfin

+0

質問に 'C'タグを付け加えるべきでしょう。 Btw、http://www.winpcap.org/pipermail/winpcap-users/2007-July/001984.htmlをご覧ください。 – Jite

答えて

3

チェックサムを再計算するには、インクリメンタルチェックサムを計算する方がよいでしょう。パケット全体を読み取るのではなく、変更したフィールドに基づいて既存のチェックサムを変更するだけです。

これは、古い値と保存する新しい値の両方を知っているときに、パケットを変更している間に行う必要があります。

基本的な考えはtcp->check += (new_val - old_val)です。

1. old_valnew_valは、2バイトで整列された(ポート番号の変更など)16ビット値である必要があります。
2.チェックサムは1の補数演算を使用しているため、フィードバックを行う必要があります。これは基本的に、tcp->check + new_val - old_valが負の場合、結果から1を引く必要があることを意味します。ここで

+1

これは正しい方法です。それは速く、データ破損のリスクがより低くなります。チェックサムをゼロから再計算すると、すでにデータに生じていた破損を隠す危険があります。 – kasperd

1

は、TCP(ないIP)のためのnetfilter API +チェックサムを組み合わせた例である:

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

は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; 

(最初にゼロが割り当てられ、チェックサムが計算され、必要がないと示されたIPチェックサムがあることに注意してください)。

uがロードされたnetfilterのモジュールに依存します(多くがあります!)彼らは(画像)を以下に示すIP層で働い異なる層、例えば、のiptableで動作します:

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

1

@ウゴレンの答えは正確ではありません。 RFC1624 https://tools.ietf.org/html/rfc1624によれば、これは時には-0(0xFFFF)を生成しますが、これは許されません。

チェックサムを計算するための正しい方法は、次のようになります。厳密に new_tcp_check = ~(~old_tcp_check + ~old_val + new_val)

関連する問題