我想基于 udp 获取 tls conn,就像:
package main
import (
"crypto/tls"
"fmt"
"io"
"net"
"time"
)
func handleConn(conn net.Conn) {
defer conn.Close()
var buf []byte = make([]byte, 2000)
for {
if n, err := conn.Read(buf); err != nil && err != io.EOF {
panic(err)
} else {
conn.Write(buf[:n])
}
}
}
func server() {
cert, err := tls.LoadX509KeyPair("./serve.cert.pem", "./serve.key.pem")
if err != nil {
panic(err)
}
config := &tls.Config{Certificates: []tls.Certificate{cert}}
conn, err := net.DialUDP("udp", &net.UDPAddr{Port: 19986}, &net.UDPAddr{Port: 19987})
if err != nil {
panic(err)
}
tconn := tls.Server(conn, config)
defer tconn.Close()
if err = tconn.Handshake(); err != nil {
panic(err)
}
handleConn(tconn)
}
func main() {
go server()
time.Sleep(time.Second)
client()
}
func client() {
conf := &tls.Config{
InsecureSkipVerify: true,
}
conn, err := net.DialUDP("udp", &net.UDPAddr{Port: 19987}, &net.UDPAddr{Port: 19986})
if err != nil {
panic(err)
}
tconn := tls.Client(conn, conf)
defer tconn.Close()
if err = tconn.Handshake(); err != nil {
panic(err)
}
_, err = conn.Write([]byte("hello"))
if err != nil {
panic(err)
}
buf := make([]byte, 100)
n, err := conn.Read(buf)
if err != nil {
panic(err)
}
fmt.Println(string(buf[:n]))
}
恐慌:
panic: read udp 127.0.0.1:19987->127.0.0.1:19986: wsarecv: A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram into was smaller than the datagram itself.
goroutine 1 [running]:
main.client()
D:/OneDrive/code/go/ctest/main.go:65 0x2d1
main.main()
D:/OneDrive/code/go/ctest/main.go:49 0x34
exit status 2
附录:serve.cert.pem
-----BEGIN CERTIFICATE-----
MIIBbjCCARSgAwIBAgIRAI jBYEYS5aBXDUedBt7PKYwCgYIKoZIzj0EAwIwEjEQ
MA4GA1UEChMHQWNtZSBDbzAeFw0yMjAxMDkxNzQxMjBaFw0yMzAxMDkxNzQxMjBa
MBIxEDAOBgNVBAoTB0FjbWUgQ28wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQy
l1/gWhTxZ3rS/XJOMLHhmkQp64EtPrEgq9SjKDpWBZQC kNZdM5xzJrv3bLqcyOS
JywZfEpTZzW7sxko4maBo0swSTAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYI
KwYBBQUHAwEwDAYDVR0TAQH/BAIwADAUBgNVHREEDTALgglsb2NhbGhvc3QwCgYI
KoZIzj0EAwIDSAAwRQIhAICxMC8o603GwL3bf42EXrtPP5/LtEIc/hjdJpilqc3b
AiBTEdrE /oCgUjsxV2RFj1 42CTGtcav4sJyCPjme0N/w==
-----END CERTIFICATE-----
服务密钥.pem
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgmH BleetLN1fK0dy
JpedWG8C2yxtb7gEEAwvdwXf6FihRANCAAQyl1/gWhTxZ3rS/XJOMLHhmkQp64Et
PrEgq9SjKDpWBZQC kNZdM5xzJrv3bLqcyOSJywZfEpTZzW7sxko4maB
-----END PRIVATE KEY-----
我试试set udp conn的buff,没用!证书只有 558 Bytes,但 UDP 的容量为 65536 Bytes。然后,我除错发现:在crypt/tls/conn.go>readRecordOrCCS c.readFromUntil(c.conn, recordHeaderLen)
,recordHeaderLen
是常数5,它加bytes.MinRead;所以读者爱好者的 len 是 517。实际上资料大小约为 700 字节。所以?我该怎么办?
uj5u.com热心网友回复:
您不能明智地期望使事情起作用:TLS(和 SSL)旨在使用另一个协议的应用层来执行。
简而言之,这意味着虽然 TLS 忽略了特定协议传输其字节的方式,但作为应用层的客户端,它期望底层堆栈具有两个属性:传输任意不透明的资料流,确保稳健性和不透明性。订单交付。在 TCP/IP 世界中,这意味着 TCP,因为 UDP 不提供 TLS 所期望的任何属性。
尽管如此,一些解决方案确实成功地在 UDP 上使用了 TLS,OpenVPN就是一个典型的例子——它使用 TLS 进行握手和初始密钥交换,同时将 UDP 作为默认和推荐的传输协议——但它们都有一层通过 UDP 实作,它“武装”了它通常在 TCP 中发现的属性:这些层处理丢弃、重新排序、复制和损坏的 UDP 帧,“汇出”到上层可以用于应用层的协议。
这基本上意味着,如果您在通过 UDP 使用 TLS 之后,您首先需要实作具有界面的自定义型别,该net.Conn
界面将使用 UDP 关联来回铲字节并向其客户端“汇出”具有鲁棒性和按顺序交付的特性——就像net.TCPConn
这样。
uj5u.com热心网友回复:
我知道了!
只需使 udp conn 成为流 io。
package main
import (
"bufio"
"crypto/tls"
"fmt"
"io"
"net"
"time"
)
func handleConn(conn net.Conn) {
defer conn.Close()
var buf []byte = make([]byte, 2000)
for {
if n, err := conn.Read(buf); err != nil && err != io.EOF {
panic(err)
} else {
fmt.Println(string(buf[:n]))
conn.Write(append([]byte("got: "), buf[:n]...))
}
}
}
func server() {
cert, err := tls.LoadX509KeyPair("./serve.cert.pem", "./serve.key.pem")
if err != nil {
panic(err)
}
config := &tls.Config{Certificates: []tls.Certificate{cert}}
conn, err := net.DialUDP("udp", &net.UDPAddr{Port: 19986}, &net.UDPAddr{Port: 19987})
if err != nil {
panic(err)
}
sconn := NewSconn(conn)
tconn := tls.Server(sconn, config)
defer tconn.Close()
handleConn(tconn)
}
func main() {
go server()
time.Sleep(time.Second)
client()
}
func client() {
conf := &tls.Config{
InsecureSkipVerify: true,
CipherSuites: []uint16{
tls.TLS_AES_128_GCM_SHA256,
},
}
conn, err := net.DialUDP("udp", &net.UDPAddr{Port: 19987}, &net.UDPAddr{Port: 19986})
if err != nil {
panic(err)
}
sconn := NewSconn(conn)
tconn := tls.Client(sconn, conf)
defer tconn.Close()
_, err = tconn.Write([]byte("hello"))
if err != nil {
panic(err)
}
buf := make([]byte, 100)
n, err := tconn.Read(buf)
if err != nil {
panic(err)
}
fmt.Println(string(buf[:n]))
}
//
//
//
//
// --------------------------------------------------
type sconn struct {
conn net.Conn
reader *bufio.Reader
}
func NewSconn(conn net.Conn) *sconn {
return &sconn{
conn: conn,
reader: bufio.NewReader(conn),
}
}
func (s *sconn) Read(b []byte) (n int, err error) {
return s.reader.Read(b)
}
func (s *sconn) Write(b []byte) (n int, err error) {
return s.conn.Write(b)
}
func (s *sconn) Close() error {
return s.conn.Close()
}
func (s *sconn) LocalAddr() net.Addr {
return s.conn.LocalAddr()
}
func (s *sconn) RemoteAddr() net.Addr {
return s.conn.RemoteAddr()
}
func (s *sconn) SetDeadline(t time.Time) error {
return s.conn.SetDeadline(t)
}
func (s *sconn) SetReadDeadline(t time.Time) error {
return s.conn.SetReadDeadline(t)
}
func (s *sconn) SetWriteDeadline(t time.Time) error {
return s.conn.SetWriteDeadline(t)
}
0 评论