初步支持 DTLS 通道

This commit is contained in:
吕海涛
2021-05-19 15:11:52 +08:00
parent a9144c9766
commit 3368eced2a
5 changed files with 203 additions and 16 deletions

View File

@@ -1,6 +1,59 @@
package handler
// 暂时没有实现
func startDtls() {
import (
"crypto/tls"
"encoding/hex"
"log"
"net"
"time"
"os"
"github.com/bjdgyc/anylink/sessdata"
"github.com/pion/dtls/v2"
"github.com/pion/dtls/v2/pkg/crypto/selfsign"
"github.com/pion/logging"
)
func startDtls() {
certificate, err := selfsign.GenerateSelfSigned()
logf := logging.NewDefaultLoggerFactory()
logf.DefaultLogLevel = logging.LogLevelTrace
f, err := os.OpenFile("/tmp/key.log", os.O_TRUNC|os.O_RDWR, 0600)
if err != nil {
panic(err)
}
config := &dtls.Config{
Certificates: []tls.Certificate{certificate},
InsecureSkipVerify: true,
ExtendedMasterSecret: dtls.DisableExtendedMasterSecret,
CipherSuites: []dtls.CipherSuiteID{dtls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
LoggerFactory: logf,
KeyLogWriter: f,
}
addr := &net.UDPAddr{IP: net.ParseIP("0.0.0.0"), Port: 4433}
ln, err := dtls.Listen("udp", addr, config)
if err != nil {
panic(err)
}
for {
c, err := ln.Accept()
if err != nil {
log.Println("Accept error", err)
continue
}
go func() {
time.Sleep(1 * time.Second)
cc := c.(*dtls.Conn)
id := hex.EncodeToString(cc.ConnectionState().SessionID)
s, ok := ss.Load(id)
log.Println("get link", id, ok)
cs := s.(*sessdata.ConnSession)
LinkDtls(c, cs)
}()
}
}

103
server/handler/link_dtls.go Normal file
View File

@@ -0,0 +1,103 @@
package handler
import (
"net"
"time"
"github.com/bjdgyc/anylink/base"
"github.com/bjdgyc/anylink/sessdata"
)
func LinkDtls(conn net.Conn, cSess *sessdata.ConnSession) {
defer func() {
base.Debug("LinkDtls return", cSess.IpAddr)
_ = conn.Close()
cSess.Close()
}()
var (
dead = time.Duration(cSess.CstpDpd+5) * time.Second
)
go dtlsWrite(conn, cSess)
for {
err := conn.SetReadDeadline(time.Now().Add(dead))
if err != nil {
base.Error("SetDeadline: ", err)
return
}
hdata := make([]byte, BufferSize)
n, err := conn.Read(hdata)
if err != nil {
base.Error("read hdata: ", err)
return
}
// 限流设置
err = cSess.RateLimit(n, true)
if err != nil {
base.Error(err)
}
switch hdata[0] {
case 0x07: // KEEPALIVE
// do nothing
base.Debug("recv keepalive", cSess.IpAddr)
case 0x05: // DISCONNECT
base.Debug("DISCONNECT", cSess.IpAddr)
return
case 0x03: // DPD-REQ
base.Debug("recv DPD-REQ", cSess.IpAddr)
if payloadOut(cSess, sessdata.LTypeIPData, 0x04, nil) {
return
}
case 0x04:
base.Debug("recv DPD-RESP", cSess.IpAddr)
case 0x00: // DATA
if payloadIn(cSess, sessdata.LTypeIPData, 0x00, hdata[1:]) {
return
}
}
}
}
func dtlsWrite(conn net.Conn, cSess *sessdata.ConnSession) {
defer func() {
base.Debug("dtlsWrite return", cSess.IpAddr)
_ = conn.Close()
cSess.Close()
}()
var (
header []byte
payload *sessdata.Payload
)
for {
select {
case payload = <-cSess.PayloadOut:
case <-cSess.CloseChan:
return
}
if payload.LType != sessdata.LTypeIPData {
continue
}
header = []byte{payload.PType}
header = append(header, payload.Data...)
n, err := conn.Write(header)
if err != nil {
base.Error("write err", err)
return
}
// 限流设置
err = cSess.RateLimit(n, false)
if err != nil {
base.Error(err)
}
}
}

View File

@@ -2,19 +2,24 @@ package handler
import (
"bytes"
"encoding/hex"
"fmt"
"log"
"net"
"net/http"
"net/http/httputil"
"os"
"sync"
"github.com/bjdgyc/anylink/base"
"github.com/bjdgyc/anylink/sessdata"
"github.com/pion/dtls/v2"
)
var hn string
var ss sync.Map
func init() {
// 获取主机名称
hn, _ = os.Hostname()
@@ -53,6 +58,14 @@ func LinkTunnel(w http.ResponseWriter, r *http.Request) {
localIp := r.Header.Get("X-Cstp-Local-Address-Ip4")
mobile := r.Header.Get("X-Cstp-License")
preMasterSecret, err := hex.DecodeString(masterSecret)
if err != nil {
log.Println(err)
w.WriteHeader(http.StatusBadRequest)
return
}
dtls.Sessions.Store(sess.DtlsSid, preMasterSecret)
cSess.SetMtu(cstpMtu)
cSess.MasterSecret = masterSecret
cSess.RemoteAddr = r.RemoteAddr
@@ -119,6 +132,7 @@ func LinkTunnel(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-DTLS-Session-ID", sess.DtlsSid)
w.Header().Set("X-DTLS-Port", "4433")
w.Header().Set("X-DTLS-DPD", fmt.Sprintf("%d", cstpDpd))
w.Header().Set("X-DTLS-Keepalive", fmt.Sprintf("%d", base.Cfg.CstpKeepalive))
w.Header().Set("X-DTLS-Rekey-Time", "5400")
w.Header().Set("X-DTLS12-CipherSuite", "ECDHE-ECDSA-AES128-GCM-SHA256")
@@ -159,5 +173,7 @@ func LinkTunnel(w http.ResponseWriter, r *http.Request) {
return
}
ss.Store(cSess.Sess.DtlsSid, cSess)
go LinkCstp(conn, cSess)
}