package main import ( "bytes" "crypto/rsa" "crypto/x509" "encoding/hex" "errors" "fmt" "log" "net" "sync" "time" ) const ( client = `ownme.ipredator.se:10002` server = `ownme.ipredator.se:10000` ) type Direction int const ( ServerClient Direction = iota ClientServer ) func (d Direction) String() string { switch d { case ServerClient: return "Server → Client" case ClientServer: return "Client → Server" } return "unknown" } type Data struct { Key *rsa.PublicKey Rnd []byte Data []byte } func (d Data) String() string { s := fmt.Sprintf("N: %v\n", d.Key) s += fmt.Sprintf("R: %x\n", d.Rnd) s += fmt.Sprintf("D: %x\n", d.Data) return s } var data = make(map[Direction]Data) func (dir Direction) sniffCert(b []byte) error { if i := bytes.Index(b, []byte{0x30, 0x82, 0x04, 0x2f}); i >= 0 { if len(b) < i+1075 { return errors.New("too short") } cert := b[i : i+1075] crt, err := x509.ParseCertificate(cert) if err != nil { return err } d := data[dir] d.Key = crt.PublicKey.(*rsa.PublicKey) data[dir] = d } return nil } func (dir Direction) sniffRnd(b []byte) error { rnd := b[0x0b:0x2b] fmt.Println(dir, "rnd", len(rnd), "bytes") d := data[dir] d.Rnd = rnd data[dir] = d return nil } func (dir Direction) sniffData(b []byte) error { if i := bytes.Index(b, []byte{0x17, 0x03, 0x03, 0x00}); i >= 0 { l := int(b[4]) d := data[dir] d.Data = b[i+5 : i+5+l] data[dir] = d } return nil } func (dir Direction) sniff(src, dst net.Conn, wg *sync.WaitGroup) { defer wg.Done() buf := make([]byte, 4096) // 1452 now := time.Now() for k := 1; ; k++ { n, err := src.Read(buf) spent := time.Since(now) if err != nil { dst.Close() return } pkg := buf[:n] if k == 1 { dir.sniffRnd(pkg) } mean := spent / time.Duration(n) fmt.Println(k, dir, n, "bytes", spent, "mean", mean, "per byte") fmt.Println(hex.Dump(pkg)) dir.sniffCert(pkg) dir.sniffData(pkg) _, err = dst.Write(pkg) now = time.Now() if err != nil { log.Println(dir, err) return } } } func main() { var wg sync.WaitGroup srv, err := net.Dial("tcp", server) if err != nil { log.Fatal(err) } defer srv.Close() cnt, err := net.Dial("tcp", client) if err != nil { log.Fatal(err) } defer cnt.Close() wg.Add(2) go ServerClient.sniff(srv, cnt, &wg) go ClientServer.sniff(cnt, srv, &wg) wg.Wait() if d, ok := data[ClientServer]; ok { fmt.Println(ClientServer) fmt.Println(d) } if d, ok := data[ServerClient]; ok { fmt.Println(ServerClient) fmt.Println(d) } }