Example #1
0
func CheckC2(s1, c2 []byte) (uint32, error) {
	server_pos := rtmp.ValidateDigest(s1, 8, rtmp.GENUINE_FMS_KEY[:36])
	if server_pos == 0 {
		server_pos = rtmp.ValidateDigest(s1, 772, rtmp.GENUINE_FMS_KEY[:36])
		if server_pos == 0 {
			return 0, errors.New("Server response validating failed")
		}
	}

	digest, err := rtmp.HMACsha256(s1[server_pos:server_pos+rtmp.SHA256_DIGEST_LENGTH], rtmp.GENUINE_FP_KEY)
	rtmp.CheckError(err, "Get digest from s1 error")

	signature, err := rtmp.HMACsha256(c2[:rtmp.RTMP_SIG_SIZE-rtmp.SHA256_DIGEST_LENGTH], digest)
	rtmp.CheckError(err, "Get signature from c2 error")

	if bytes.Compare(signature, c2[rtmp.RTMP_SIG_SIZE-rtmp.SHA256_DIGEST_LENGTH:]) != 0 {
		return 0, errors.New("Server signature mismatch")
	}
	return server_pos, nil
}
Example #2
0
func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "%s version[%s]\r\nUsage: %s [OPTIONS]\r\n", programName, version, os.Args[0])
		flag.PrintDefaults()
	}
	flag.Parse()
	l := log.NewLogger(".", "proxy", nil, 60, 3600*24, true)
	rtmp.InitLogger(l)
	defer l.Close()

	// listen
	listen, err := net.Listen("tcp", ":1935")
	if err != nil {
		fmt.Println("Listen error", err)
		os.Exit(-1)
	}
	defer listen.Close()

	for {
		iconn, err := listen.Accept()
		if err != nil {
			fmt.Println("Accept error", err)
			os.Exit(-1)
		}
		if iconn == nil {
			fmt.Println("iconn is nil")
			os.Exit(-1)
		}
		defer iconn.Close()
		// Handshake
		// C>>>P: C0+C1
		ibr := bufio.NewReader(iconn)
		ibw := bufio.NewWriter(iconn)
		c0, err := ibr.ReadByte()
		if c0 != 0x03 {
			fmt.Printf("C>>>P: C0(0x%2x) != 0x03\n", c0)
			os.Exit(-1)
		}
		c1 := make([]byte, rtmp.RTMP_SIG_SIZE)
		_, err = io.ReadAtLeast(ibr, c1, rtmp.RTMP_SIG_SIZE)
		// Check C1
		var clientDigestOffset uint32
		if clientDigestOffset, err = CheckC1(c1, true); err != nil {
			fmt.Println("C>>>P: Test C1 err:", err)
			os.Exit(-1)
		}
		// P>>>S: Connect Server
		oconn, err := net.Dial("tcp", "192.168.20.111:1935")
		if err != nil {
			fmt.Println("P>>>S: Dial server err:", err)
			os.Exit(-1)
		}
		defer oconn.Close()
		obr := bufio.NewReader(oconn)
		obw := bufio.NewWriter(oconn)
		// P>>>S: C0+C1
		if err = obw.WriteByte(c0); err != nil {
			fmt.Println("P>>>S: Write C0 err:", err)
			os.Exit(-1)
		}
		if _, err = obw.Write(c1); err != nil {
			fmt.Println("P>>>S: Write C1 err:", err)
			os.Exit(-1)
		}
		if err = obw.Flush(); err != nil {
			fmt.Println("P>>>S: Flush err:", err)
			os.Exit(-1)
		}
		// P<<<S: Read S0+S1+S2
		s0, err := obr.ReadByte()
		if err != nil {
			fmt.Println("P<<<S: Read S0 err:", err)
			os.Exit(-1)
		}
		if c0 != 0x03 {
			fmt.Printf("P<<<S: S0(0x%2x) != 0x03\n", s0)
			os.Exit(-1)
		}
		s1 := make([]byte, rtmp.RTMP_SIG_SIZE)
		_, err = io.ReadAtLeast(obr, s1, rtmp.RTMP_SIG_SIZE)
		if err != nil {
			fmt.Println("P<<<S: Read S1 err:", err)
			os.Exit(-1)
		}
		s2 := make([]byte, rtmp.RTMP_SIG_SIZE)
		_, err = io.ReadAtLeast(obr, s2, rtmp.RTMP_SIG_SIZE)
		if err != nil {
			fmt.Println("P<<<S: Read S2 err:", err)
			os.Exit(-1)
		}

		// C<<<P: Send S0+S1+S2
		if err = ibw.WriteByte(s0); err != nil {
			fmt.Println("C<<<P: Write S0 err:", err)
			os.Exit(-1)
		}
		if _, err = ibw.Write(s1); err != nil {
			fmt.Println("C<<<P: Write S1 err:", err)
			os.Exit(-1)
		}
		if _, err = ibw.Write(s2); err != nil {
			fmt.Println("C<<<P: Write S2 err:", err)
			os.Exit(-1)
		}
		if err = ibw.Flush(); err != nil {
			fmt.Println("C<<<P: Flush err:", err)
			os.Exit(-1)
		}

		// C>>>P: Read C2
		c2 := make([]byte, rtmp.RTMP_SIG_SIZE)
		_, err = io.ReadAtLeast(ibr, c2, rtmp.RTMP_SIG_SIZE)

		// Check S2
		server_pos := rtmp.ValidateDigest(s1, 8, rtmp.GENUINE_FP_KEY[:30])
		if server_pos == 0 {
			server_pos = rtmp.ValidateDigest(s1, 772, rtmp.GENUINE_FP_KEY[:30])
			if server_pos == 0 {
				fmt.Println("P<<<S: S1 position check error")
				os.Exit(-1)
			}
		}

		digest, err := rtmp.HMACsha256(c1[clientDigestOffset:clientDigestOffset+rtmp.SHA256_DIGEST_LENGTH], rtmp.GENUINE_FMS_KEY)
		rtmp.CheckError(err, "Get digest from c1 error")

		signature, err := rtmp.HMACsha256(s2[:rtmp.RTMP_SIG_SIZE-rtmp.SHA256_DIGEST_LENGTH], digest)
		rtmp.CheckError(err, "Get signature from s2 error")

		if bytes.Compare(signature, s2[rtmp.RTMP_SIG_SIZE-rtmp.SHA256_DIGEST_LENGTH:]) != 0 {
			fmt.Println("Server signature mismatch")
			os.Exit(-1)
		}

		digestResp, err := rtmp.HMACsha256(s1[server_pos:server_pos+rtmp.SHA256_DIGEST_LENGTH], rtmp.GENUINE_FP_KEY)
		rtmp.CheckError(err, "Generate C2 HMACsha256 digestResp")
		signatureResp, err := rtmp.HMACsha256(c2[:rtmp.RTMP_SIG_SIZE-rtmp.SHA256_DIGEST_LENGTH], digestResp)
		if bytes.Compare(signatureResp, c2[rtmp.RTMP_SIG_SIZE-rtmp.SHA256_DIGEST_LENGTH:]) != 0 {
			fmt.Println("C2 mismatch")
			os.Exit(-1)
		}

		// P>>>S: Send C2
		if _, err = obw.Write(c2); err != nil {
			fmt.Println("P>>>S: Write C2 err:", err)
			os.Exit(-1)
		}
		if err = obw.Flush(); err != nil {
			fmt.Println("P>>>S: Flush err:", err)
			os.Exit(-1)
		}

		// Proxy
		go io.Copy(iconn, oconn)
		go io.Copy(oconn, iconn)
	}
}
Example #3
0
func TryHandshakeByVLC() net.Conn {
	// listen
	listen, err := net.Listen("tcp", ":1935")
	if err != nil {
		fmt.Println("Listen error", err)
		os.Exit(-1)
	}
	defer listen.Close()

	iconn, err := listen.Accept()
	if err != nil {
		fmt.Println("Accept error", err)
		os.Exit(-1)
	}
	if iconn == nil {
		fmt.Println("iconn is nil")
		os.Exit(-1)
	}
	defer iconn.Close()
	// Handshake
	// C>>>P: C0+C1
	ibr := bufio.NewReader(iconn)
	ibw := bufio.NewWriter(iconn)
	c0, err := ibr.ReadByte()
	if c0 != 0x03 {
		fmt.Printf("C>>>P: C0(0x%2x) != 0x03\n", c0)
		os.Exit(-1)
	}
	c1 := make([]byte, rtmp.RTMP_SIG_SIZE)
	_, err = io.ReadAtLeast(ibr, c1, rtmp.RTMP_SIG_SIZE)
	// Check C1
	var clientDigestOffset uint32
	if clientDigestOffset, err = CheckC1(c1, true); err != nil {
		fmt.Println("C>>>P: Test C1 err:", err)
		os.Exit(-1)
	}
	// P>>>S: Connect Server
	oconn, err := net.Dial("tcp", "192.168.20.111:1935")
	if err != nil {
		fmt.Println("P>>>S: Dial server err:", err)
		os.Exit(-1)
	}
	//	defer oconn.Close()
	obr := bufio.NewReader(oconn)
	obw := bufio.NewWriter(oconn)
	// P>>>S: C0+C1
	if err = obw.WriteByte(c0); err != nil {
		fmt.Println("P>>>S: Write C0 err:", err)
		os.Exit(-1)
	}
	if _, err = obw.Write(c1); err != nil {
		fmt.Println("P>>>S: Write C1 err:", err)
		os.Exit(-1)
	}
	if err = obw.Flush(); err != nil {
		fmt.Println("P>>>S: Flush err:", err)
		os.Exit(-1)
	}
	// P<<<S: Read S0+S1+S2
	s0, err := obr.ReadByte()
	if err != nil {
		fmt.Println("P<<<S: Read S0 err:", err)
		os.Exit(-1)
	}
	if c0 != 0x03 {
		fmt.Printf("P<<<S: S0(0x%2x) != 0x03\n", s0)
		os.Exit(-1)
	}
	s1 := make([]byte, rtmp.RTMP_SIG_SIZE)
	_, err = io.ReadAtLeast(obr, s1, rtmp.RTMP_SIG_SIZE)
	if err != nil {
		fmt.Println("P<<<S: Read S1 err:", err)
		os.Exit(-1)
	}
	s2 := make([]byte, rtmp.RTMP_SIG_SIZE)
	_, err = io.ReadAtLeast(obr, s2, rtmp.RTMP_SIG_SIZE)
	if err != nil {
		fmt.Println("P<<<S: Read S2 err:", err)
		os.Exit(-1)
	}

	// C<<<P: Send S0+S1+S2
	if err = ibw.WriteByte(s0); err != nil {
		fmt.Println("C<<<P: Write S0 err:", err)
		os.Exit(-1)
	}
	if _, err = ibw.Write(s1); err != nil {
		fmt.Println("C<<<P: Write S1 err:", err)
		os.Exit(-1)
	}
	if _, err = ibw.Write(s2); err != nil {
		fmt.Println("C<<<P: Write S2 err:", err)
		os.Exit(-1)
	}
	if err = ibw.Flush(); err != nil {
		fmt.Println("C<<<P: Flush err:", err)
		os.Exit(-1)
	}

	// C>>>P: Read C2
	c2 := make([]byte, rtmp.RTMP_SIG_SIZE)
	_, err = io.ReadAtLeast(ibr, c2, rtmp.RTMP_SIG_SIZE)

	// Check S2
	server_pos := rtmp.ValidateDigest(s1, 8, rtmp.GENUINE_FP_KEY[:30])
	if server_pos == 0 {
		server_pos = rtmp.ValidateDigest(s1, 772, rtmp.GENUINE_FP_KEY[:30])
		if server_pos == 0 {
			fmt.Println("P<<<S: S1 position check error")
			os.Exit(-1)
		}
	}

	digest, err := rtmp.HMACsha256(c1[clientDigestOffset:clientDigestOffset+rtmp.SHA256_DIGEST_LENGTH], rtmp.GENUINE_FMS_KEY)
	rtmp.CheckError(err, "Get digest from c1 error")

	signature, err := rtmp.HMACsha256(s2[:rtmp.RTMP_SIG_SIZE-rtmp.SHA256_DIGEST_LENGTH], digest)
	rtmp.CheckError(err, "Get signature from s2 error")

	if bytes.Compare(signature, s2[rtmp.RTMP_SIG_SIZE-rtmp.SHA256_DIGEST_LENGTH:]) != 0 {
		fmt.Println("Server signature mismatch")
		os.Exit(-1)
	}

	digestResp, err := rtmp.HMACsha256(s1[server_pos:server_pos+rtmp.SHA256_DIGEST_LENGTH], rtmp.GENUINE_FP_KEY)
	rtmp.CheckError(err, "Generate C2 HMACsha256 digestResp")
	signatureResp, err := rtmp.HMACsha256(c2[:rtmp.RTMP_SIG_SIZE-rtmp.SHA256_DIGEST_LENGTH], digestResp)
	if bytes.Compare(signatureResp, c2[rtmp.RTMP_SIG_SIZE-rtmp.SHA256_DIGEST_LENGTH:]) != 0 {
		fmt.Println("C2 mismatch")
		os.Exit(-1)
	}

	// P>>>S: Send C2
	if _, err = obw.Write(c2); err != nil {
		fmt.Println("P>>>S: Write C2 err:", err)
		os.Exit(-1)
	}
	if err = obw.Flush(); err != nil {
		fmt.Println("P>>>S: Flush err:", err)
		os.Exit(-1)
	}
	return oconn
}