试图找到一段代码,负责发送带有RST-flag的TCP数据包

时间:2017-03-08 13:26:13

标签: go tcp network-programming

我试图了解kdar生成以下代码的方式:

package main

import (
    "github.com/google/gopacket"
    "github.com/google/gopacket/layers"
    "log"
    "net"
    "os"
    "strconv"
    "time"
)

// get the local ip and port based on our destination ip
func localIPPort(dstip net.IP) (net.IP, int) {
    serverAddr, err := net.ResolveUDPAddr("udp", dstip.String()+":12345")
    if err != nil {
        log.Fatal(err)
    }

    // We don't actually connect to anything, but we can determine
    // based on our destination ip what source ip we should use.
    if con, err := net.DialUDP("udp", nil, serverAddr); err == nil {
        if udpaddr, ok := con.LocalAddr().(*net.UDPAddr); ok {
            return udpaddr.IP, udpaddr.Port
        }
    }
    log.Fatal("could not get local ip: " + err.Error())
    return nil, -1
}

func main() {
    if len(os.Args) != 3 {
        log.Printf("Usage: %s <host/ip> <port>\n", os.Args[0])
        os.Exit(-1)
    }
    log.Println("starting")

    dstaddrs, err := net.LookupIP(os.Args[1])
    if err != nil {
        log.Fatal(err)
    }

    // parse the destination host and port from the command line os.Args
    dstip := dstaddrs[0].To4()
    var dstport layers.TCPPort
    if d, err := strconv.ParseInt(os.Args[2], 10, 16); err != nil {
        log.Fatal(err)
    } else {
        dstport = layers.TCPPort(d)
    }

    srcip, sport := localIPPort(dstip)
    srcport := layers.TCPPort(sport)
    log.Printf("using srcip: %v", srcip.String())

    // Our IP header... not used, but necessary for TCP checksumming.
    ip := &layers.IPv4{
        SrcIP:    srcip,
        DstIP:    dstip,
        Protocol: layers.IPProtocolTCP,
    }
    // Our TCP header
    tcp := &layers.TCP{
        SrcPort: srcport,
        DstPort: dstport,
        Seq:     1105024978,
        SYN:     true,
        Window:  14600,
    }
    tcp.SetNetworkLayerForChecksum(ip)

    // Serialize.  Note:  we only serialize the TCP layer, because the
    // socket we get with net.ListenPacket wraps our data in IPv4 packets
    // already.  We do still need the IP layer to compute checksums
    // correctly, though.
    buf := gopacket.NewSerializeBuffer()
    opts := gopacket.SerializeOptions{
        ComputeChecksums: true,
        FixLengths:       true,
    }
    if err := gopacket.SerializeLayers(buf, opts, tcp); err != nil {
        log.Fatal(err)
    }

    conn, err := net.ListenPacket("ip4:tcp", "0.0.0.0")
    if err != nil {
        log.Fatal(err)
    }
    log.Println("writing request")
    if _, err := conn.WriteTo(buf.Bytes(), &net.IPAddr{IP: dstip}); err != nil {
        log.Fatal(err)
    }

    // Set deadline so we don't wait forever.
    if err := conn.SetDeadline(time.Now().Add(10 * time.Second)); err != nil {
        log.Fatal(err)
    }

    for {
        b := make([]byte, 4096)
        log.Println("reading from conn")
        n, addr, err := conn.ReadFrom(b)
        if err != nil {
            log.Println("error reading packet: ", err)
            return
        } else if addr.String() == dstip.String() {
            // Decode a packet
            packet := gopacket.NewPacket(b[:n], layers.LayerTypeTCP, gopacket.Default)
            // Get the TCP layer from this packet
            if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
                tcp, _ := tcpLayer.(*layers.TCP)

                if tcp.DstPort == srcport {
                    if tcp.SYN && tcp.ACK {
                        log.Printf("Port %d is OPEN\n", dstport)
                    } else {
                        log.Printf("Port %d is CLOSED\n", dstport)
                    }
                    return
                }
            }
        } else {
            log.Printf("Got packet not matching addr")
        }
    }
}

如果我理解正确,该代码会将带有SYN-flag的原始TCP数据包发送到服务器并等待响应。使用wireshark我发现在从服务器收到响应(SYN-ACK)后,客户端发送一个带有RST标志的数据包。我无法理解,哪一段代码负责发送带有RST-flag的TCP数据包。

0 个答案:

没有答案