関連記事
Goメモ-306 (go-packetメモ-01)(ネットワークインターフェースを表示) - いろいろ備忘録日記
Goメモ-307 (go-packetメモ-02)(流れるパケットをキャプチャする)(OpenLive) - いろいろ備忘録日記
Goメモ-308 (go-packetメモ-03)(pcapファイルを読み込み)(OpenOffline) - いろいろ備忘録日記
Goメモ-309 (go-packetメモ-04)(BPFフィルタを設定)(SetBPFFilter) - いろいろ備忘録日記
Goメモ-310 (go-packetメモ-05)(*pcap.Packetの中身を表示) - いろいろ備忘録日記
Goメモ-311 (go-packetメモ-06)(*layers.Ethernetの情報を表示) - いろいろ備忘録日記
Goメモ-312 (go-packetメモ-07)(*layers.ARPの情報を表示) - いろいろ備忘録日記
Goメモ-313 (go-packetメモ-08)(*layers.ICMPv4の情報を表示) - いろいろ備忘録日記
Goメモ-314 (go-packetメモ-09)(*layers.IPv4の情報を表示) - いろいろ備忘録日記
Goメモ-315 (go-packetメモ-10)(*layers.TCPの情報を表示) - いろいろ備忘録日記
Goメモ-316 (go-packetメモ-11)(*layers.UDPの情報を表示) - いろいろ備忘録日記
Goメモ-317 (go-packetメモ-12)(アプリケーションレイヤーの情報を表示) - いろいろ備忘録日記
Goメモ-321 (go-packetメモ-13)(HTTPの情報を表示) - いろいろ備忘録日記
Goメモ-323 (go-packetメモ-14)(DNSの情報を表示) - いろいろ備忘録日記
Goメモ-324 (go-packetメモ-15)(DNSSECの情報を表示) - いろいろ備忘録日記
GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ
概要
以下、自分用のメモです。忘れないうちにメモメモ。。。
GoでWireSharkやtcpdumpのようにパケットを直接見たいときなどに利用できるライブラリに
というのがあります。
今まで使ったこと無かったのですが、使うと面白かったので自分用のメモ代わりにちょこちょこ残しておこうと思います。
Linux (Ubuntu) 上で遊んでいますので、Windowsの場合はWinPcap (WireSharkをインストールするときについでにインストールできたはず)が必要になると思います。
インストール
libpcap
が必要ですので、以下でインストールします。
$ sudo apt install libpcap-dev
あと、tcpdumpが入っていない場合は以下もついでに入れておきます。(これはオプショナルです)
$ sudo apt install tcpdump
あと、FTPサーバが無ければインストールして簡易で立てましょう。
$ sudo apt-get update
$ sudo apt-get install -y vsftpd
試してみる
使い方に関しては、上に挙げている go-packet の godoc の方に詳しく書かれています。
今回は、FTPの中身を見てみます。
アプリケーションレイヤーを取得して、ペイロードが取れれば後はそれをFTPだと解釈してやれば良いはずです。
main.go
// Package main is the example of FTP using go-packet. package main import ( "fmt" "log" "os" "os/signal" "time" "github.com/google/gopacket" "github.com/google/gopacket/layers" "github.com/google/gopacket/pcap" ) var ( appLog = log.New(os.Stderr, "", 0) ) func main() { if err := run(); err != nil { panic(err) } } func run() error { const ( device = "lo" filter = "tcp and port 21" snapshotLen = int32(1600) promiscuous = false timeout = 1 * time.Second ) defer func() { appLog.Println("DONE") }() // -------------------------------------- // Open capture handle // -------------------------------------- var ( handle *pcap.Handle err error ) handle, err = pcap.OpenLive(device, snapshotLen, promiscuous, timeout) if err != nil { return fmt.Errorf("error open handle: %w", err) } defer handle.Close() // -------------------------------------- // Apply capture filter (optional) // -------------------------------------- if filter != "" { err = handle.SetBPFFilter(filter) if err != nil { return fmt.Errorf("error apply filter: %w", err) } } // -------------------------------------- // Set signal handler // -------------------------------------- var ( doneCh = make(chan struct{}) sigCh = make(chan os.Signal, 1) ) signal.Notify(sigCh, os.Interrupt) // -------------------------------------- // Make packet source and display. // -------------------------------------- var ( dataSource gopacket.PacketDataSource = handle decoder gopacket.Decoder = handle.LinkType() packetSource *gopacket.PacketSource = gopacket.NewPacketSource(dataSource, decoder) packetCh <-chan gopacket.Packet = packetSource.Packets() ) appLog.Println("START") LOOP: for { select { case <-sigCh: close(doneCh) break LOOP case p, ok := <-packetCh: if !ok { break LOOP } if err = see(p); err != nil { return err } } } return nil } func see(p gopacket.Packet) error { // // レイヤーを確認 // tcpLayer := p.Layer(layers.LayerTypeTCP) if tcpLayer == nil { return nil } // // ペイロードを取得 // var ( tcp = tcpLayer.(*layers.TCP) payload = tcp.LayerPayload() ) if len(payload) == 0 { appLog.Printf("[Src Port ] %v", tcp.SrcPort) appLog.Printf("[Dst Port ] %v", tcp.DstPort) appLog.Printf("[Seq Number ] %v", tcp.Seq) appLog.Printf("[Ack Number ] %v", tcp.Ack) appLog.Printf("[Window Size ] %v", tcp.Window) appLog.Printf("[TCP Flags - SYN] %v", tcp.SYN) appLog.Printf("[TCP Flags - ACK] %v", tcp.ACK) appLog.Printf("[TCP Flags - PSH] %v", tcp.PSH) appLog.Printf("[TCP Flags - RST] %v", tcp.RST) appLog.Printf("[TCP Flags - FIN] %v", tcp.FIN) appLog.Printf("[Checksum ] %v", tcp.Checksum) appLog.Printf("[Urgent Pointer ] %v", tcp.Urgent) appLog.Println("------------------------------------") return nil } // // ペイロードを文字列に変換してFTPとしての解析を試みる // var ( payloadStr = string(payload) ) defer func() { appLog.Println("------------------------------------") }() appLog.Printf("[FTP] %s\n", payloadStr) return nil }
Taskfile.yml
タスク定義は以下のような感じ。
applayer-ftp: desc: See FTP info dir: cmd/applayer/ftp cmds: - cmd: echo Please start the FTP server in advance. silent: true - go build -o gopacket-ftp main.go - sudo ./gopacket-ftp & - cmd: read silent: true - sudo pkill gopacket-ftp
以下、Gitpod上で実行してみた結果です。
vsftpを臨時で立てて、それとやり取りしているパケットを見ます。
$ sudo apt-get update
$ sudo apt-get install -y vsftpd
設定ファイルを調整。ローカルでしか使わないのでセキュリティは無視です。
/etc/vsftpd.conf
anonymous_enable=YES local_enable=YES write_enable=YES local_umask=022 chroot_local_user=NO
起動します。
$ sudo mkdir -p /var/run/vsftpd/empty $ sudo vsftpd /etc/vsftpd.conf
別のターミナルを起動して
$ task applayer-ftp
もう一つ別のターミナルを起動して
$ sudo apt-get install -y lftp $ lftp -u anonymous, anonymous@localhost lftp anonymous@localhost:~> ls lftp anonymous@localhost:/> bye
そうすると、taskを実行しているターミナルに以下のように出力されます。
[Src Port ] 52584 [Dst Port ] 21(ftp) [Seq Number ] 3285394225 [Ack Number ] 0 [Window Size ] 43690 [TCP Flags - SYN] true [TCP Flags - ACK] false [TCP Flags - PSH] false [TCP Flags - RST] false [TCP Flags - FIN] false [Checksum ] 65072 [Urgent Pointer ] 0 ------------------------------------ [Src Port ] 21(ftp) [Dst Port ] 52584 [Seq Number ] 2228490639 [Ack Number ] 3285394226 [Window Size ] 43690 [TCP Flags - SYN] true [TCP Flags - ACK] true [TCP Flags - PSH] false [TCP Flags - RST] false [TCP Flags - FIN] false [Checksum ] 65072 [Urgent Pointer ] 0 ------------------------------------ [Src Port ] 52584 [Dst Port ] 21(ftp) [Seq Number ] 3285394226 [Ack Number ] 2228490640 [Window Size ] 342 [TCP Flags - SYN] false [TCP Flags - ACK] true [TCP Flags - PSH] false [TCP Flags - RST] false [TCP Flags - FIN] false [Checksum ] 65064 [Urgent Pointer ] 0 ------------------------------------ [FTP] 220 (vsFTPd 3.0.5) ------------------------------------ [Src Port ] 52584 [Dst Port ] 21(ftp) [Seq Number ] 3285394226 [Ack Number ] 2228490660 [Window Size ] 342 [TCP Flags - SYN] false [TCP Flags - ACK] true [TCP Flags - PSH] false [TCP Flags - RST] false [TCP Flags - FIN] false [Checksum ] 65064 [Urgent Pointer ] 0 ------------------------------------ [FTP] FEAT ------------------------------------ [Src Port ] 21(ftp) [Dst Port ] 52584 [Seq Number ] 2228490660 [Ack Number ] 3285394232 [Window Size ] 342 [TCP Flags - SYN] false [TCP Flags - ACK] true [TCP Flags - PSH] false [TCP Flags - RST] false [TCP Flags - FIN] false [Checksum ] 65064 [Urgent Pointer ] 0 ------------------------------------ [FTP] 211-Features: ------------------------------------ [FTP] EPRT ------------------------------------ [FTP] EPSV ------------------------------------ [Src Port ] 52584 [Dst Port ] 21(ftp) [Seq Number ] 3285394232 [Ack Number ] 2228490682 [Window Size ] 342 [TCP Flags - SYN] false [TCP Flags - ACK] true [TCP Flags - PSH] false [TCP Flags - RST] false [TCP Flags - FIN] false [Checksum ] 65064 [Urgent Pointer ] 0 ------------------------------------ [FTP] MDTM ------------------------------------ [FTP] PASV ------------------------------------ [FTP] REST STREAM ------------------------------------ [FTP] SIZE ------------------------------------ [Src Port ] 52584 [Dst Port ] 21(ftp) [Seq Number ] 3285394232 [Ack Number ] 2228490717 [Window Size ] 342 [TCP Flags - SYN] false [TCP Flags - ACK] true [TCP Flags - PSH] false [TCP Flags - RST] false [TCP Flags - FIN] false [Checksum ] 65064 [Urgent Pointer ] 0 ------------------------------------ [FTP] TVFS ------------------------------------ [FTP] 211 End ------------------------------------ [Src Port ] 52584 [Dst Port ] 21(ftp) [Seq Number ] 3285394232 [Ack Number ] 2228490731 [Window Size ] 342 [TCP Flags - SYN] false [TCP Flags - ACK] true [TCP Flags - PSH] false [TCP Flags - RST] false [TCP Flags - FIN] false [Checksum ] 65064 [Urgent Pointer ] 0 ------------------------------------ [FTP] AUTH TLS ------------------------------------ [FTP] 530 Please login with USER and PASS. ------------------------------------ [FTP] USER anonymous ------------------------------------ [FTP] 331 Please specify the password. ------------------------------------ [FTP] PASS ------------------------------------ [FTP] 230 Login successful. ------------------------------------ [FTP] PWD ------------------------------------ [FTP] 257 "/" is the current directory ------------------------------------ [FTP] PASV ------------------------------------ [FTP] 227 Entering Passive Mode (127,0,0,1,209,75). ------------------------------------ [FTP] LIST ------------------------------------ [FTP] 150 Here comes the directory listing. ------------------------------------ [FTP] 226 Directory send OK. ------------------------------------ [Src Port ] 52584 [Dst Port ] 21(ftp) [Seq Number ] 3285394282 [Ack Number ] 2228490979 [Window Size ] 342 [TCP Flags - SYN] false [TCP Flags - ACK] true [TCP Flags - PSH] false [TCP Flags - RST] false [TCP Flags - FIN] false [Checksum ] 65064 [Urgent Pointer ] 0 ------------------------------------ [FTP] QUIT ------------------------------------ [FTP] 221 Goodbye. ------------------------------------ [Src Port ] 21(ftp) [Dst Port ] 52584 [Seq Number ] 2228490993 [Ack Number ] 3285394288 [Window Size ] 342 [TCP Flags - SYN] false [TCP Flags - ACK] true [TCP Flags - PSH] false [TCP Flags - RST] false [TCP Flags - FIN] true [Checksum ] 65064 [Urgent Pointer ] 0 ------------------------------------ [Src Port ] 52584 [Dst Port ] 21(ftp) [Seq Number ] 3285394288 [Ack Number ] 2228490994 [Window Size ] 342 [TCP Flags - SYN] false [TCP Flags - ACK] true [TCP Flags - PSH] false [TCP Flags - RST] false [TCP Flags - FIN] true [Checksum ] 65064 [Urgent Pointer ] 0 ------------------------------------ [Src Port ] 21(ftp) [Dst Port ] 52584 [Seq Number ] 2228490994 [Ack Number ] 3285394289 [Window Size ] 342 [TCP Flags - SYN] false [TCP Flags - ACK] true [TCP Flags - PSH] false [TCP Flags - RST] false [TCP Flags - FIN] false [Checksum ] 65064 [Urgent Pointer ] 0 ------------------------------------ task: [applayer-ftp] sudo pkill gopacket-ftp
ちゃんとFTPのやり取りが見えていますね。
リポジトリ
上のサンプルなどは、以下のリポジトリでアップしています。ご参考までに。
参考情報
Goのおすすめ書籍
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。