• 締切済み
  • 困ってます

C言語でTCPの3way handshake

(C言語)Linuxのpacket socket(socket(AF?PACKET, SOCK_DGRAM, htons(ETH_P_IP))) を使ってTCPの3way handshakeをOSのプロトコルスタックに頼らず自力で挑戦しています。 RFCやほかの技術本をよんでIPヘッダやTCPヘッダの実装は一応できたのですが、肝心のsynパケットを送った後のackパケットが返ってきません。 wiresharkでは問題なくsynパケットと認識できているのですが、きっとどこかに不備があるはずです。 そこでC, C++ Javaでもいいのでこのプログラムの実装例が載っているサイトなどを教えてください。(英語でもかまいません)

共感・応援の気持ちを伝えよう!

  • 回答数4
  • 閲覧数1990
  • ありがとう数1

みんなの回答

  • 回答No.4

> ところで、jjk65536さんはこういった情報をどこから入手しているのですか。 > raw socketやpacket socketを解説してくれているサイトはかなり少ないように感じます。 > 掲示板やこういった質問サイトも普段から利用されているのでしょうか。 基本的にはGoogle検索で調べてますね。 自分の英語読解力があてにならないので、基本的には海外のサンプルコードを 自分で動かして見ながら期待動作するように作ったりしてます。 教えてGoo!では普段C言語あたりを見たり回答したりしてます。 ちなみに、パケットキャプチャ中にだれかがSynをだしてたんですよ。 それにはRstの応答が返ってるんですね。 試しにそれと同じパケットを自分で出してみたんですが、Rst応答が 来なかったんです。 なんなんでしょうね。セキュリティ上の理由で同じパケットが来ても Rst応答はしない、とかあるかもしれません。 気になる内容なので、詳しい方が現れてズバっと解決してくれると僕も嬉しいんですが。

共感・感謝の気持ちを伝えよう!

質問者からのお礼

ありがとうございました。

質問者からの補足

>> ちなみに、パケットキャプチャ中にだれかがSynをだしてたんですよ。 それにはRstの応答が返ってるんですね。 試しにそれと同じパケットを自分で出してみたんですが、Rst応答が 来なかったんです。 なぜだかさっぱりです。僕の作ったパケットが悪いと思っていたのですが、原因はそれだけではないのかもしれませんね。 LinuxやBSDあたりのプロトコルスタックの実装をソースコードを読んで理解できればいいのですが... ちょっとハードルが高いです。 本当にズバッと解決できたらいいのですが。

関連するQ&A

  • 任意のTCPパケットを送信するプログラムの実装

    TCP 通信確立後、任意のパケットを送信するプログラムを 作成しようと考えてます。ここでの任意のパケットとは、 下記のように TCP ヘッダの値を色々と設定したパケットを 指します。 ・TCP ヘッダのすべての制御フラグを有効にしたパケット ・TCP ヘッダのチェックサムを意図的に間違えたパケット 任意のデータを送信するだけであれば、通常の socket プログラムで実装できると思うのですが、TCP ヘッダを 色々と設定するプログラムとなると、どんな実装になるの でしょうか。C だと SOCK_RAW で socket 通信するよう、 実装するのでしょうか。 実装は C、perl を考えてます。

  • TCPの接続処理と終了処理について

    TCPでコネクションを確立するとき、制御フラグでSYN、SYN+ACK、ACKで3パケットをやりとしますが、終了手順のときは、FIN、ACK、FIN、ACKと4パケットをやりとりします。 これは何故でしょうか? コネクション確立時と同じく、FIN、FIN+ACK、ACKにしないのは何故でしょうか?教えてください。

  • 3ウェイハンドシェイクについて

    TCP通信を行う場合、3ウェイハンドシェイクでパイプをつくるようですが、その始め(通信の始め)にSYNを送り、その返信にACKを返す仕組みになっていると思います。そのSYNを送るときに、MAC、IP、TCPヘッダーをつけたパケットを送ると思うのですが、アプリが作ったデータもまた送るのでしょうか?通信できるかどうかを確かめるだけなら最初の通信はデータが必要ないと思うのですが・・・。また、データをつけないパケットなども送ることができるのか(フォーマットに合わないような気が・・・)どうかもあわせてお願いします。

  • 回答No.3

> だとしたら`TCP header length(24bytes)` / 4 = 6であっているのではないでしょうか。 すんません、合ってましたね。 普段Wiresharkの解析に頼りっきりで、ちゃんと自分で読んでなかったから そんなことも忘れてました。 さて、提示して頂いたバイナリをパケットにして手元のPCで出力してみましたが、 やっぱりRstも来ないですねぇ。 他に詳しい方が現れるかとも思っていたんですが、いらっしゃらないみたいですね…。 力及ばず申し訳ないです。 ところでSOCK_RAWって生ソケットですよね? これでTCPヘッダの大半をOSが作ってくれるとは初耳です。 どこのサイトに解説があったのか、教えて頂けませんか? 私は普段SOCK_RAWをEtherフレームからCで構築するときに使ってるんですが…

共感・感謝の気持ちを伝えよう!

質問者からの補足

>> ところでSOCK_RAWって生ソケットですよね? これでTCPヘッダの大半をOSが作ってくれるとは初耳です。どこのサイトに解説があったのか、教えて頂けませんか? すみません、大嘘でした。 ハードディスクの片隅から探し出したところ0のダミーで埋めてあっただけで一応TCPヘッダは作っていました。そのときのソケットはsocket(AF_INET, SOCK_RAW, IPPROTO_TCP)でした。 どこのサイトにあったかは覚えていません。たぶん海外のサイトだったと思います。 packet socketは自分で作ったヘッダはkernelによって書きかえられませんが、RAW SOCKETはソースIPやチェックサム等はkernelによって書き換えられるので勘違いしていました。 (まぁ、考えようによってはkernelが作ってくれているともいえなくもありませんが) ところで、jjk65536さんはこういった情報をどこから入手しているのですか。 raw socketやpacket socketを解説してくれているサイトはかなり少ないように感じます。 掲示板やこういった質問サイトも普段から利用されているのでしょうか。

  • 回答No.2

見ました。 TCPヘッダ内のヘッダレングスが96バイトって間違ってません? 24バイトくらいになるかと思いますが。 以下のように通信しようとしていると読めましたが、合ってますか? tcp/ip src=127.0.0.1:14818 dst=127.0.0.1:61256 そうであれば、そのPCの61256番ポートでは何かのデーモンがListen していますか? 例えば、パケットキャプチャ中にターミナルで # telnet 127.0.0.1 61256 としたときに、期待したAck(またはRst)は観測できますか? 目で追っていったので、読み間違いがあるかもしれません。 指摘が間違ってたらすんません。

共感・感謝の気持ちを伝えよう!

質問者からの補足

>> 以下のように通信しようとしていると読めましたが、合ってますか? はい、あっています。 >> TCPヘッダ内のヘッダレングスが96バイトって間違ってません? "TCPヘッダ内のヘッダレングス"というのはTCPヘッダの12バイト目から4ビット間のRFCでいうところの"Data offset"のことですか? だとしたら`TCP header length(24bytes)` / 4 = 6であっているのではないでしょうか。 間違っていたらすみません。(そのときはTCPヘッダのどの部分かご教授お願いします) 一応wiresharkと自作のパケットキャプチャーソフトではTCP header lengthは24byteとでていますが... いつもはLAN内のほかのPCで実験していますが、今回は自身に送りました。 >> そうであれば、そのPCの61256番ポートでは何かのデーモンがListenしていますか? 送信ポートは乱数で決めています。61256ポートで待機しているのはbind, listen, acceptでブロッキングしている自前のサーバプログラムではだめですか? またtelnetで自前のプログラムにconnect()したときはwiresharkとtcpdumpで3way handshakeが正常に動作していることを確認しました。自前プログラムがポートでlistenしていない場合はrstが帰ってくることも確認しました。 前にどこかのWebページでみたAF_INET, SOCK_RAWをつかったプログラムは今回と同じ環境できちんと動作しましたが、この場合TCPヘッダのControl Bitsを除くIPヘッダ全体とTCPヘッダの大半はOSが作ってくれていたので、今回はEthernet headerを除くすべてのヘッダを自前で作りたいです。 よろしくお願いします。

  • 回答No.1

OpenSouceでしたら、LinuxよりBSDのネットワークスタックが読みやすいと 詳しい人に聞いたことがあります。(自分ではまだ読んでません、すんません) それよりも、送信したSynパケットのダンプデータでも貼ってみてはいかがでしょう? スクリーンキャプチャを撮って画像添付するとか。 わかる方が間違いを指摘してくれると思いますよ。私も見ます。 また、対向のサーバはそのSynパケットに対して正しくAckを返せるように 調整されているのでしょうか? そのポートはサーバでオープンされていますか? そのポートをTCPでListenしているデーモンは可動していますか? 対向サーバ上のWiresharkでは、Synパケットは観測できていますか? その辺がOKなら、やはりパケットのどこかに間違いがあるのだと思います。 見てみたいですね。

共感・感謝の気持ちを伝えよう!

質問者からの補足

ヘッダに設定したポートにサーバーを走らせてもうんともすんとも言わず、さらに普通listenしていないポートにsynパケットを送るとrstパケットが帰ってくるはずなのですが、それも帰ってきません。多分IPヘッダidやTCPヘッダのack numberあたりが怪しい。(完全に初心者) 絶対にどこかでとんちんかんなことになってるはずです。 以下wiresharkで確認したループバックに送ったsynパケットの16進ダンプ(MSS=1460のオプション付き) (Ethernet header)00 11 11 94 7f 34 00 00 00 00 00 00 08 00 (ここからIP header)45 00 00 2c 70 ea 40 00 40 06 cb df 7f 00 00 01 7f 00 00 01 (ここからTCP header)39 e2 ef 48 00 03 1b 32 00 00 00 00 60 02 0c cf f6 c7 00 00 02 04 05 b4

関連するQ&A

  • Windowsでパケットモニタソフトの作成

    Windowsでパケットモニタを作成するにはどうしたらよいでしょうか? Linuxでは s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ALL)); でEthernetを直接利用してパケットを受信するようなのですが、Windowsの場合はどうすればEthernetを直接利用できるのでしょうか? よろしくお願いします。

  • C++言語でのWinsock2を使用したパケットモニタの作成

    こんにちは 現在Winsock2を使用したパケットモニタを作成しています パケットを受信できるプログラムは作成することができましたが、TCPパケットが期待した順番通りに受信できません 例えば、3WAYハンドシェイクのパケットのやり取りで、期待しているパケットの受信順は 1. host ---> net: SYN 2. host <--- net: SYN,ACK 3. host ---> net: ACK ですが、パケットモニタでは以下の順番でパケットを受信しています 1. host ---> net: SYN 2. host ---> net: ACK 3. host <--- net: SYN,ACK hostから送信されるパケットが先に受信されているような感じですが、これらを時刻順に受信するオプションなどはあるのでしょうか? もしあるならどのように設定すればよろしいのでしょうか? (ソケットなどの設定内容) 初期化  WSADATA wsd;  WSAStartup(MAKEWORD(2, 2), &wsd) ソケット作成  SOCKET sock;  sock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED) 無差別受信モードに設定  int op = RCVALL_ON;  WSAIoctl(sock, SIO_RCVALL, &op, sizeof(op), NULL, 0, &dword, NULL, NULL) パケットの受信  WSABUF wsb;  DWORD len = 0;  DWORD flag = 0;  WSARecv(sock, &wsb, 1, &len, &flag, NULL, NULL)

  • WiresharkのFlow Graph

    現在WiresharkのFlow Graphという機能を使用して、クライアント端末がサーバー端末へのTCP通信での3ウェイハンドシェイクのパケットやりとりを観測したいと思っています。 次のようなパケットをモニターしました。 |Time | 192.168.1.111 | | | | 192.168.1.222 | |6.402 | PSH, ACK - Len: 1212 |Seq = 1 Ack = 1 | |(6057) ------------------> (5000) | |6.606 | PSH, ACK - Len: 1212 |Seq = 1 Ack = 1 | |(6057) ------------------> (5000) | |6.835 | PSH, ACK - Len: 1212 |Seq = 1 Ack = 1213 | |(6057) <------------------ (5000) | |7.039 | ACK | |Seq = 1213 Ack = 1213 | |(6057) ------------------> (5000) | |7.150 | ACK | |Seq = 1213 Ack = 1213 このパケットのやりとりを観ていて思ったのですが、TCP通信は3ウェイハンドシェイクは SYN--->SYN ACK---> ACK という順序でのパケットのやりとりをクライアントとサーバー間で行うと思っていたのですが、 PSH, ACK ----> PSH, ACK ----> ACK ----> ACK このような順序になっているように思うのですが、これはなぜなのかご教授頂けないでしょうか? どうぞ、よろしくお願い致します。

  • HTTPアクセスの処理

    HTTPで「http://www.yahoo.co.jp」にアクセスしようとした場合、どのような内部処理が行われるのでしょうか? 大まか流れとして 1・DNSによる名前解決 2・TCPセッションの確立 3・HTTP要求 と考えてます。(ARP解決は省略します) 1・DNSによる名前解決 プロトコルスタックの流れだとHTTP→DNS→TCP→IP→Ethernetでネットワークに送信され、応答がEthernet→IP→TCP→DNSになると思います。 2・TCPセッションの確立(省略) SYN→SYN ACK→ACK 3・HTTP要求(省略) HTTP GET→HTTP 200 OK わからない部分は1・DNSによる名前解決が終わったあとどうやって2・TCPセッションの確立に移行するのかということです。 (同様に2・TCPセッションの確立が終わったあとに3・HTTP要求)

  • C言語開発環境について

    このプログラムを実行出来るコンパイラ?あるいは開発環境を紹介して頂けませんか?出来れば無償版がいいです。よろしくお願い致します。 #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") int main() { WSAData wsaData; SOCKET sock; struct sockaddr_in addr; WSAStartup(MAKEWORD(2,0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(3054); addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.3"); sendto(sock, "HELLO", 5, 0, (struct sockaddr *)&addr, sizeof(addr)); closesocket(sock); WSACleanup(); return 0; }

  • IPパケット、TCPパケット、UDPパケット

    IPパケット、TCPパケット、UDPパケットのヘッダ構造とはどんなものなのでしょうか?また各々のフィールドがどのような役割を担っているのかについて教えてください。お願いしますm(__)m

  • BBルータでTCP通信のデータ部が捨てられている?

    インターネット上のServerと自宅PC間でWebを併用したデータ交換をしているのですが、ある限られたデータ部のみ、自宅のBBルータにより毎回捨てられているようで受信できません。 Serverと自宅PC(Client)にEtherealを同時に仕掛けPacketをモニタリングしました。 Server側のLogを見る限り、Serverは該当データを正しく送り、BBルータも正しく受信しているようです。 しかし、Client側のLogを見ると、その部分は Len=0 になっており、ヘッダ部だけのPacketが送信されて来たかのようになっております。 BBルータの設定可能項目では、いたって通常の設定になっており、また、自宅PCはWindowsXP SP2でFirewallはOff、ウィルス対策ソフトもアンインストール状態で実験しております。今回のトラブル以外は全てにおいて不具合は発生しておりません。 何か単純なTCP規則違反に該当しているのではとRFC793も確認したのですが原因がわかりません。 該当部分のEtherealのLogは以下の通りです。 何か大事なことを忘れていそうなのですが、どなたかご教授をお願い致します。 <Server側Log> ※No.292~294は3way handshakeです。 ※()内はTCP詳細部の内容抜粋です。 ※Server側のPortはWeb併用なので80番をそのまま使用。 No. SRC  DIST  Prot  Info 295 Client Server HTTP Continuation or non-HTTP Trafic 296 Server Client HTTP Continuation or non-HTTP Trafic (http > 62327 [PSH,ACK] Seq=1 Ack=24 Win=65512 Len=90) 297 Server Client TCP http > 62327 [FIN,ACK] Seq=91 Ack=24 Win=65512 Len=0 298 Client Server TCP 62327 > http [ACK] Seq=24 Ack=92 Win=65535 Len=0 299 Client Server TCP 62327 > http [FIN,ACK] Seq=24 Ack=92 Win=65535 Len=0 300 Server Client TCP http > 62327 [ACK] Seq=92 Ack=25 Win=65512 Len=0 <Client側Log> ※No.295と297~300はServer側Logと矛盾はありません。 No. SRC  DIST  Prot  Info 296 Server Client TCP http > 1157 [PSH,ACK] Seq=1 Ack=24 Win=65512 Len=0 以上

  • socket通信でのフィルタリング

    linux環境にてC言語でUDPソケットのプログラムを作成しています。 Aの端末からUDPで受信してパケットヘッダの表示及び、宛先アドレスや宛先ポート番号 を書き換えてBの端末にUDPで送信します。 そこで下記の関数を使用して受信しているのですが、パケットキャプチャのように なんでも受信してしまいます。 socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) これを特定のポート番号だけ受信(フィルタ)するにはどのようにすれば良いのでしょうか?

  • C言語エラーの解決法教えてください。

    以下のプログラムで6行目にこのようなエラー表示がでてきたのですが、どうすれば良いですか? 1 IntelliSense: 識別子 "WSAData" が定義されていません 2 IntelliSense: 識別子 "wsaData" が定義されていません #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") int main() { WSAData; wsaData; SOCKET sock; struct sockaddr_in addr; WSAStartup(MAKEWORD(2,0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(9750); addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.8 "); sendto(sock, "HELLO", 5, 0, (struct sockaddr *)&addr, sizeof(addr)); closesocket(sock); WSACleanup(); return 0; } 教えてください。宜しくお願いします。

  • パケットキャプチャについて

    パケットキャプチャについて wiresharkでパケットキャプチャをやっております。tcpでsynのパケットのみを収集したいのですが、現在では、 (1)ファイルの読み込み (2)フィルタの条件でtcp.flag.fin == 0 and tcp.fla.syn ==1 and tcp.flg.ack == 0 と入れフィルタリング。 (3)結果のファイルを保存 となって大変時間がかかります。cuiでコマンドライン上で一発ですませられる方法はありませんか?