예제 #1
0
파일: gather.go 프로젝트: yangxingpping/nat
func getReflexive(sock *net.UDPConn) (*net.UDPAddr, error) {
	serverAddr, err := net.ResolveUDPAddr("udp", *stunserver)
	if err != nil {

		return nil, errors.New("Couldn't resolve STUN server")
	}

	var tid [12]byte
	if _, err = rand.Read(tid[:]); err != nil {
		return nil, err
	}

	request, err := stun.BindRequest(tid[:], nil, true, false)
	if err != nil {
		return nil, err
	}

	n, err := sock.WriteTo(request, serverAddr)
	if err != nil {
		return nil, err
	}
	if n < len(request) {
		return nil, err
	}

	var buf [1024]byte
	n, _, err = sock.ReadFromUDP(buf[:])
	if err != nil {
		return nil, err
	}

	packet, err := stun.ParsePacket(buf[:n], nil)
	if err != nil {
		return nil, err
	}

	if packet.Class != stun.ClassSuccess || packet.Method != stun.MethodBinding || packet.Addr == nil || !bytes.Equal(tid[:], packet.Tid[:]) {
		return nil, errors.New("No address provided by STUN server")
	}

	return packet.Addr, nil
}
예제 #2
0
파일: nat.go 프로젝트: yangxingpping/nat
func (e *attemptEngine) xmit() (time.Time, error) {
	now := time.Now()
	var ret time.Time
	var err error

	for i := range e.attempts {
		if e.attempts[i].timeout.Before(now) {
			e.attempts[i].timeout = time.Now().Add(probeTimeout)
			e.attempts[i].tid, err = stun.RandomTid()
			if err != nil {
				return time.Time{}, err
			}
			packet, err := stun.BindRequest(e.attempts[i].tid, nil, false, e.attempts[i].chosen)
			if err != nil {
				return time.Time{}, err
			}
			e.sock.WriteToUDP(packet, e.attempts[i].Addr)
		}
		if ret.IsZero() || e.attempts[i].timeout.Before(ret) {
			ret = e.attempts[i].timeout
		}
	}
	return ret, nil
}
예제 #3
0
파일: client.go 프로젝트: yangxingpping/nat
func main() {
	flag.Parse()
	serverAddr, err := net.ResolveUDPAddr("udp", *server)
	if err != nil {
		fmt.Println("Couldn't resolve", *server)
		os.Exit(1)
	}

	tid := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc}
	request, err := stun.BindRequest(tid, nil, true, false)
	if err != nil {
		fmt.Println("Failed to build STUN request:", err)
		os.Exit(1)
	}

	sock, err := net.ListenUDP("udp", &net.UDPAddr{Port: *sourcePort})
	if err != nil {
		fmt.Println("Couldn't listen on UDP port", *sourcePort)
		os.Exit(1)
	}
	if err := sock.SetDeadline(time.Now().Add(10 * time.Second)); err != nil {
		fmt.Println("Couldn't set the socket timeout:", err)
		os.Exit(1)
	}

	n, err := sock.WriteTo(request, serverAddr)
	if err != nil {
		fmt.Println("Couldn't send STUN request:", err)
		os.Exit(1)
	}
	if n < len(request) {
		fmt.Println("Short write")
		os.Exit(1)
	}

	buf := make([]byte, 1024)
	n, _, err = sock.ReadFromUDP(buf)
	if err != nil {
		fmt.Println("Error reading STUN response:", err)
		os.Exit(1)
	}
	sock.Close()

	packet, err := stun.ParsePacket(buf[:n], nil)
	if err != nil {
		fmt.Println("Failed to parse STUN packet:", err)
		os.Exit(1)
	}

	if packet.Error != nil {
		fmt.Println("STUN server returned an error:", packet.Error)
		os.Exit(1)
	}
	if packet.Addr == nil {
		fmt.Println("STUN server didn't provide a reflexive address")
		os.Exit(1)
	}

	fmt.Printf("According to STUN server %s, port %d maps to %s on your NAT\n",
		*server, *sourcePort, packet.Addr)
}