euniclusRubyの学習のためポートスキャンツールを作ります。Pythonにはscapyという便利なライブラリーがあります。Rubyにそのようなものがあるのか調べてませんしわからないので、スクラッチで作ることになります。調査を怠けた以上これは致し方ないです。感想ソケット作成synスキャンを行うためrawsocketを使う必要があります。socketを作成します。c言語どほとんど変わりないはありませんでした。アドレスファミリー、ソケットタイプ、プロトコルを指定します。tcpヘッダを自分で編集するための設定としてソケットタイプにSOCK_RAWプロトコルにIPPROTO_TCPを指定します。Socket::open(Socket::AF_INET,Socket::SOCK_RAW,Socket::IPPROTO_TCP)socendTCPヘッダーの作成ヘッダーの作成方法に関しては僕が知らないだけでもっといいやり方があるかもしれません。今回は以下の方法で作成しました。TCPはパケットの内容が壊れていないかを判定するためチェックサムを計算しますが、その時に擬似ipヘッダーというものを加えます。これは正しい通信相手からのパケットかどうかを判断するためだそうです。諸々のデータを決定してpackで文字列にします。packに渡している「n2N2C2n3」は値の型と数を表しています。「n3」は2byteの値を3個といった具合に配列の値を文字列に変換してくれます。tcpヘッダーの構成を考えると「n2N2C2n3」をpackに渡すことになります。特別なことはしていません。[sport,dport,seq,ackseq,doff,flags,window,cksum,urp]data.pack("n2N2C2n3")endチェックサムの計算パケットのチェックサムを計算する関数です。0xffffendスキャン1から65535までのポートを対象にスキャンを開始します。ひとつのポートにつき10回までスキャンを試みます。以下の終了条件を満たすまでパケットを送り続けます。10回パケットの送受信をするsyn,ackブラグがたったパケットを受信するフラグ上記の2以外の状態のパケットを受信する項目として十分ではないかもしれませんが、ポートスキャナーとして最低限の動きはしてくれると思います。open"endbreakendendendendendendパケットからヘッダーを抽出ターゲットからパケットを受信したあと、そこからipヘッダーとtcpヘッダーを取得します。パケットを送信する際にpackを使用して文字列にして送信しました。今回は文字列に対しunpackを使用して配列を取得します。extract_tcp(packet)packet.unpack("n2N2C2n3")end全体ソースコード全体はこうなりました。PortScannerとしてクラスを作成しました。以下のようにスキャンします。PortScanner.new()scanner.scan(target_ip)実行するときのコマンドと結果はこうなります。open感想Pythonに似ている気がします。Pythonでも作ってみたいと思います。ほとんど変わらないかと。