Slide 1

Slide 1 text

GoナニモワカラナイけどChatGPTと共に 解決したい課題が解けるかやってみた October 23, 2024. Fukuoka.go#20

Slide 2

Slide 2 text

@akase244 October 23, 2024. Fukuoka.go#20 WebApplicationEngineer() ->InfrastructureEngineer() );

Slide 3

Slide 3 text

Fukuoka.php(最近開催できてないですが) October 23, 2024. Fukuoka.go#20

Slide 4

Slide 4 text

PHPカンファレンス福岡2015-19,23-24 October 23, 2024. Fukuoka.go#20

Slide 5

Slide 5 text

@tsunagimefm October 23, 2024. Fukuoka.go#20

Slide 6

Slide 6 text

第19回(三宅さん、小田さん) October 23, 2024. Fukuoka.go#20

Slide 7

Slide 7 text

October 23, 2024. Fukuoka.go#20 本日取り上げるのは

Slide 8

Slide 8 text

October 23, 2024. Fukuoka.go#20 死活監視

Slide 9

Slide 9 text

October 23, 2024. Fukuoka.go#20

Slide 10

Slide 10 text

October 23, 2024. Fukuoka.go#20

Slide 11

Slide 11 text

October 23, 2024. Fukuoka.go#20 諸事情あって死活監視を 自前でやりたい

Slide 12

Slide 12 text

October 23, 2024. Fukuoka.go#20 死活監視の仕組みは シンプルな方法でやりたい

Slide 13

Slide 13 text

October 23, 2024. Fukuoka.go#20 ping

Slide 14

Slide 14 text

October 23, 2024. Fukuoka.go#20 ● pingコマンド ○ ICMP(Internet Control Message Protocol) ○ 監視先のホスト名・アドレス ○ 実行回数 ○ RTT(Round Trip Time)

Slide 15

Slide 15 text

October 23, 2024. Fukuoka.go#20 $ ping www.google.com -c 3 PING www.google.com (123.123.123.123) 56(84) bytes of data. 64 bytes from www.example.net (123.123.123.123): icmp_seq=1 ttl=116 time=20.6 ms 64 bytes from www.example.net (123.123.123.123): icmp_seq=2 ttl=116 time=21.4 ms 64 bytes from www.example.net (123.123.123.123): icmp_seq=3 ttl=116 time=24.5 ms --- www.google.com ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2002ms rtt min/avg/max/mdev = 20.604/22.165/24.490/1.675 ms 実行結果

Slide 16

Slide 16 text

October 23, 2024. Fukuoka.go#20 ping はシンプルで便利ですが

Slide 17

Slide 17 text

October 23, 2024. Fukuoka.go#20 クラウド事業者によっては ICMPが許可されていない

Slide 18

Slide 18 text

October 23, 2024. Fukuoka.go#20 監視したい対象のサーバーでは HTTP(S)が動いている

Slide 19

Slide 19 text

October 23, 2024. Fukuoka.go#20 ICMPではなくTCPで 疎通確認できると嬉しい

Slide 20

Slide 20 text

October 23, 2024. Fukuoka.go#20 TCPを監視する仕組み

Slide 21

Slide 21 text

October 23, 2024. Fukuoka.go#20 hping3 / nping

Slide 22

Slide 22 text

October 23, 2024. Fukuoka.go#20 hping3 ● Kali Linuxに同梱。単独のコマンドでもインストール可能。 ● Ubuntuではaptでインストール可能。 ● Macはbrewのフォーミュラのメンテが2024年の2月で切れている。

Slide 23

Slide 23 text

October 23, 2024. Fukuoka.go#20 $ sudo hping3 www.google.com -p 443 -S -c 3 HPING www.google.com (XXXXXXXXXXXXXXX 123.123.123.123): S set, 40 headers + 0 data bytes len=46 ip=123.123.123.123 ttl=120 DF id=0 sport=443 flags=SA seq=0 win=65535 rtt=27.9 ms len=46 ip=123.123.123.123 ttl=120 DF id=0 sport=443 flags=SA seq=1 win=65535 rtt=25.7 ms len=46 ip=123.123.123.123 ttl=120 DF id=0 sport=443 flags=SA seq=2 win=65535 rtt=19.5 ms --- www.google.com hping statistic --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max = 19.5/24.4/27.9 ms 実行結果

Slide 24

Slide 24 text

October 23, 2024. Fukuoka.go#20 nping ● nmapに同梱。 ● Ubuntuではaptでインストール可能。 ● Macではbrewでインストール可能。

Slide 25

Slide 25 text

October 23, 2024. Fukuoka.go#20 % sudo nping www.google.com --tcp -p 443 --flags syn -c 3 Starting Nping 0.7.95 ( https://nmap.org/nping ) at 2024-10-09 22:33 JST SENT (0.0120s) TCP 192.168.0.126:2941 > 142.250.206.228:443 S ttl=64 id=32827 iplen=40 seq=1858308333 win=1480 RCVD (0.0325s) TCP 142.250.206.228:443 > 192.168.0.126:2941 SA ttl=120 id=0 iplen=44 seq=2406887558 win=65535 SENT (1.0122s) TCP 192.168.0.126:2941 > 142.250.206.228:443 S ttl=64 id=32827 iplen=40 seq=1858308333 win=1480 RCVD (1.0313s) TCP 142.250.206.228:443 > 192.168.0.126:2941 SA ttl=120 id=0 iplen=44 seq=2422489814 win=65535 SENT (2.0124s) TCP 192.168.0.126:2941 > 142.250.206.228:443 S ttl=64 id=32827 iplen=40 seq=1858308333 win=1480 RCVD (2.0405s) TCP 142.250.206.228:443 > 192.168.0.126:2941 SA ttl=120 id=0 iplen=44 seq=2438261292 win=65535 Max rtt: 27.952ms | Min rtt: 19.055ms | Avg rtt: 22.476ms Raw packets sent: 3 (120B) | Rcvd: 3 (138B) | Lost: 0 (0.00%) Nping done: 1 IP address pinged in 2.04 seconds 実行結果

Slide 26

Slide 26 text

October 23, 2024. Fukuoka.go#20 これでいいじゃん

Slide 27

Slide 27 text

October 23, 2024. Fukuoka.go#20 と、思ってたら

Slide 28

Slide 28 text

October 23, 2024. Fukuoka.go#20 $ sudo hping3 監視対象ホスト -p 80 -S -c 5 HPING 監視対象ホスト (eth0 123.123.123.123): S set, 40 headers + 0 data bytes len=46 ip=123.123.123.123 ttl=51 DF id=0 sport=80 flags=SA seq=0 win=64240 rtt=19.3 ms len=46 ip=123.123.123.123 ttl=51 DF id=0 sport=80 flags=SA seq=1 win=64240 rtt=19.6 ms len=46 ip=123.123.123.123 ttl=51 DF id=0 sport=80 flags=SA seq=2 win=64240 rtt=19.3 ms len=52 ip=123.123.123.123 ttl=51 DF id=0 sport=80 flags=SA seq=0 win=64240 rtt=0.0 ms len=46 ip=123.123.123.123 ttl=51 DF id=29975 sport=80 flags=A seq=0 win=251 rtt=0.0 ms --- 監視対象ホスト hping statistic --- 3 packets transmitted, 5 packets received, -66% packet loss round-trip min/avg/max = 19.3/19.4/19.6 ms hping3の実行結果

Slide 29

Slide 29 text

October 23, 2024. Fukuoka.go#20 $ sudo hping3 監視対象ホスト -p 80 -S -c 5 HPING 監視対象ホスト (eth0 123.123.123.123): S set, 40 headers + 0 data bytes len=46 ip=123.123.123.123 ttl=51 DF id=0 sport=80 flags=SA seq=0 win=64240 rtt=19.3 ms len=46 ip=123.123.123.123 ttl=51 DF id=0 sport=80 flags=SA seq=1 win=64240 rtt=19.6 ms len=46 ip=123.123.123.123 ttl=51 DF id=0 sport=80 flags=SA seq=2 win=64240 rtt=19.3 ms len=52 ip=123.123.123.123 ttl=51 DF id=0 sport=80 flags=SA seq=0 win=64240 rtt=0.0 ms len=46 ip=123.123.123.123 ttl=51 DF id=29975 sport=80 flags=A seq=0 win=251 rtt=0.0 ms --- 監視対象ホスト hping statistic --- 3 packets transmitted, 5 packets received, -66% packet loss round-trip min/avg/max = 19.3/19.4/19.6 ms hping3の実行結果

Slide 30

Slide 30 text

October 23, 2024. Fukuoka.go#20 -66% packet loss

Slide 31

Slide 31 text

October 23, 2024. Fukuoka.go#20 どうしてこうなった

Slide 32

Slide 32 text

October 23, 2024. Fukuoka.go#20 原因

Slide 33

Slide 33 text

October 23, 2024. Fukuoka.go#20 hping3を実行しているサーバーで hping3以外がHTTP(S)の送受信を行っており、 hping3実行時に関係ないパケットを受信していました。 hping3は受信したパケットの中身を確認していないので、同じタ イミングで発生した監視対象サーバーからの受信パケットを全て 拾ってしまう作りになっています。 ※同僚がhping3のソースを読んで解説してくれました。 ※どうやらnpingも同様の作りになっているようです。

Slide 34

Slide 34 text

October 23, 2024. Fukuoka.go#20 これが今回解決したい課題

Slide 35

Slide 35 text

October 23, 2024. Fukuoka.go#20 よし

Slide 36

Slide 36 text

October 23, 2024. Fukuoka.go#20 自分で作ればいいじゃない

Slide 37

Slide 37 text

October 23, 2024. Fukuoka.go#20

Slide 38

Slide 38 text

October 23, 2024. Fukuoka.go#20 それっぽいコード

Slide 39

Slide 39 text

October 23, 2024. Fukuoka.go#20 何度か同じように質問してみると まずは簡易なやり方が提示されました

Slide 40

Slide 40 text

October 23, 2024. Fukuoka.go#20 for i := 0; i < *count; i++ { start := time.Now() conn, err := net.Dial("tcp", *host+":"+*port) if err != nil { fmt.Println("Error:", err) continue } defer conn.Close() rtt := time.Since(start) fmt.Printf("RTT: %v\n", rtt) rttTimes = append(rttTimes, rtt) net.Dialを利用するパターン

Slide 41

Slide 41 text

October 23, 2024. Fukuoka.go#20 for i := 0; i < count; i++ { start := time.Now() conn, err := net.DialTimeout("tcp", address, 2*time.Second) rtt := time.Since(start) if err != nil { fmt.Printf("Request %d: Connection failed: %s\n", i+1, err) } else { fmt.Printf("Request %d: Connected, RTT = %v\n", i+1, rtt) rttTimes = append(rttTimes, rtt) conn.Close() } net.DialTimeoutを利用するパターン

Slide 42

Slide 42 text

October 23, 2024. Fukuoka.go#20 net.Dialのパターンの実行結果 $ go run sample_dial.go -host tsunagi.me -port 80 -c 2 RTT: 51.351408ms RTT: 34.728687ms Min RTT: 34.728687ms, Max RTT: 51.351408ms, Avg RTT: 43.040047ms

Slide 43

Slide 43 text

$ go run sample_dial_timeout.go tsunagi.me 80 2 PING tsunagi.me:80 (tsunagi.me:80) Request 1: Connected, RTT = 56.609141ms Request 2: Connected, RTT = 32.416619ms --- tsunagi.me:80 statistics --- 2 packets transmitted, 2 packets received RTT min/avg/max = 32.416619ms/44.51288ms/56.609141ms October 23, 2024. Fukuoka.go#20 net.DialTimeoutの実行結果

Slide 44

Slide 44 text

October 23, 2024. Fukuoka.go#20 実行結果はどちらもそれっぽい

Slide 45

Slide 45 text

October 23, 2024. Fukuoka.go#20 TCPのソケットプログラミングの場合 ● root権限が必要 ● ケイパビリティの設定が必要 今回は実行時にroot権限が求められな かったので、net.Dialではシステムコール を使ってOSの機能を呼び出してる?

Slide 46

Slide 46 text

October 23, 2024. Fukuoka.go#20

Slide 47

Slide 47 text

October 23, 2024. Fukuoka.go#20 またそれっぽいコード

Slide 48

Slide 48 text

October 23, 2024. Fukuoka.go#20 packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for packet := range packetSource.Packets() { // 応答をチェック if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil { tcp := tcpLayer.(*layers.TCP) if tcp.SYN && tcp.ACK { duration := time.Since(start) fmt.Printf("Received SYN-ACK from %s:%d in %v\n", targetIP, targetPort, duration) return duration, nil } } } gopacketを使っていてかなりそれっぽい?

Slide 49

Slide 49 text

October 23, 2024. Fukuoka.go#20 $ sudo go run sample_dial_timeout.go tsunagi.me 80 # github.com/google/gopacket/pcap /root/go/pkg/mod/github.com/google/[email protected]/pcap/pcap_unix.go:34:10: fatal error: pcap.h: No such file or directory 34 | #include | ^~~~~~~~ compilation terminated. なんか怒られた

Slide 50

Slide 50 text

October 23, 2024. Fukuoka.go#20

Slide 51

Slide 51 text

October 23, 2024. Fukuoka.go#20 $ sudo apt install libpcap-dev

Slide 52

Slide 52 text

October 23, 2024. Fukuoka.go#20 $ sudo go run sample_dial_timeout.go tsunagi.me 80 # command-line-arguments ./main.go:33:2: declared and not used: tcpHeader ./main.go:41:8: assignment mismatch: 1 variable but conn.WriteTo returns 2 values ./main.go:41:21: multiple-value ipHeader.Marshal() (value of type ([]byte, error)) in single-value context ./main.go:79:23: cannot use port (variable of type string) as int value in argument to sendSYN またなんか怒られた

Slide 53

Slide 53 text

October 23, 2024. Fukuoka.go#20 この後 何度かやり取りを繰り返します

Slide 54

Slide 54 text

October 23, 2024. Fukuoka.go#20 やり取りを繰り返す中で

Slide 55

Slide 55 text

October 23, 2024. Fukuoka.go#20 実行元ホストのIPアドレスを 「192.168.1.1」に決め打ちしたり

Slide 56

Slide 56 text

October 23, 2024. Fukuoka.go#20 実行元ホストのデバイスを 「eth0」に決め打ちしたり

Slide 57

Slide 57 text

October 23, 2024. Fukuoka.go#20 それっぽく動いてるように見せかけて 常に「100% packet loss」だったり

Slide 58

Slide 58 text

October 23, 2024. Fukuoka.go#20 ChatGPTさんは結構適当でした

Slide 59

Slide 59 text

October 23, 2024. Fukuoka.go#20 本質じゃないところで 割と時間を取られることに

Slide 60

Slide 60 text

October 23, 2024. Fukuoka.go#20 結論としては まだ完成していません。。。

Slide 61

Slide 61 text

October 23, 2024. Fukuoka.go#20 最終的にやりたい事としては

Slide 62

Slide 62 text

October 23, 2024. Fukuoka.go#20 ● hping3のようにホスト、ポート番号、実行回数を引数に指定す る。 ● SYNフラグを送信して、SYN/ACKを受信したら成功とする。 ● 実行時にシーケンス番号、ACK番号を確認して、送信したパ ケットの戻りパケットであることを保証したい。 ● 1回実行する毎にRTT(Round Trip Time)を表示する。 ● 実行が完了したらRTTのmin/max/avgを表示する。

Slide 63

Slide 63 text

October 23, 2024. Fukuoka.go#20 引き続き実装を進めていくつもりです

Slide 64

Slide 64 text

October 23, 2024. Fukuoka.go#20 このあたりの知見をお持ちの方が いたらぜひ教えてください

Slide 65

Slide 65 text

October 23, 2024. Fukuoka.go#20 Thanks! Have a good programming!!