init
This commit is contained in:
commit
7213e64b89
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.idea
|
||||
shadowTLS
|
||||
shadowTLS.exe
|
32
README.md
Normal file
32
README.md
Normal file
@ -0,0 +1,32 @@
|
||||
# Shadow-TLS
|
||||
### TLS伪装代理 -- 包装任意TCP连接为真正合法域名的TLS连接
|
||||
## 基本原理
|
||||
与服务端连接后,服务端会请求指定合法的HTTPS域名(例如www.apple.com)并转发TLS握手流量,与客户端TLS握手成功后后续将转发实际的TCP流量,对审计设备(防火墙/上网行为管理软件/零信任网关)而言你是访问一个合法且是真实证书的HTTPS网站.
|
||||
|
||||
## 使用场景
|
||||
- 在有域名白名单的情况下需要将流量转发出去
|
||||
- 对抗网络审计设备的审查
|
||||
|
||||
## 使用方法
|
||||
- 服务端示例:
|
||||
监听端口443,收到请求后先创造到www.apple.com的TLS握手,随后转发本地的8888端口流量到客户端
|
||||
```shell
|
||||
./shadowtls server -l 0.0.0.0:443 -f www.apple.com:443 -t 127.0.0.1:8888
|
||||
```
|
||||
|
||||
- 客户端示例:
|
||||
```shell
|
||||
./shadowtls client -l 0.0.0.0:11222 -s 145.142.63.32:443 -d www.apple.com
|
||||
```
|
||||
|
||||
## 功能特性
|
||||
- TLS连接多路复用,减少TLS握手次数
|
||||
|
||||
## 安全性特别说明
|
||||
- 包装的TCP流量没有加密,如有需求请加密后再转发
|
||||
- 多路复用特性使用了smux的框架,有协议特征,有更进一步需求需修改源码二次加密
|
||||
- TLS后续流量没有进行Application Data封装,深层次的协议分析可以发现此特征
|
||||
|
||||
## 特别说明
|
||||
- 感谢v2ex网友ihciah的思路灵感.
|
||||
- 仅供技术研究,请勿用于非法用途.
|
4
build.bat
Normal file
4
build.bat
Normal file
@ -0,0 +1,4 @@
|
||||
set GOOS=windows
|
||||
go build -ldflags "-s -w" -trimpath -o shadowTLS.exe
|
||||
set GOOS=linux
|
||||
go build -ldflags "-s -w" -trimpath -o shadowTLS
|
35
cmd/client.go
Normal file
35
cmd/client.go
Normal file
@ -0,0 +1,35 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"shadowTLS/shadow"
|
||||
)
|
||||
|
||||
type ClientParam struct {
|
||||
ListenAddr string
|
||||
ServerAddr string
|
||||
SNI string
|
||||
}
|
||||
|
||||
var (
|
||||
clientParams *ClientParam
|
||||
clientCmd = &cobra.Command{
|
||||
Use: "client",
|
||||
Short: "Client mode",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
client := shadow.NewClient(clientParams.ListenAddr, clientParams.ServerAddr, clientParams.SNI)
|
||||
client.Start()
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
clientParams = &ClientParam{}
|
||||
clientCmd.Flags().StringVarP(&clientParams.ListenAddr, "listen", "l", "0.0.0.0:18080", "Listen address and port")
|
||||
clientCmd.Flags().StringVarP(&clientParams.ServerAddr, "saddr", "s", "", "Server address and port")
|
||||
clientCmd.Flags().StringVarP(&clientParams.SNI, "domain", "d", "", "Domain name used for TLS Handshake")
|
||||
clientCmd.MarkFlagRequired("listen")
|
||||
clientCmd.MarkFlagRequired("saddr")
|
||||
clientCmd.MarkFlagRequired("sni")
|
||||
rootCmd.AddCommand(clientCmd)
|
||||
}
|
25
cmd/root.go
Normal file
25
cmd/root.go
Normal file
@ -0,0 +1,25 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
rootCmd = &cobra.Command{
|
||||
Use: "shadowTLS",
|
||||
Short: "Pack TCP connection and perform real TLS handshake to confuse firewall",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
rootCmd.CompletionOptions.DisableDefaultCmd = true
|
||||
}
|
||||
|
||||
func Execute() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
35
cmd/server.go
Normal file
35
cmd/server.go
Normal file
@ -0,0 +1,35 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"shadowTLS/shadow"
|
||||
)
|
||||
|
||||
type ServerParam struct {
|
||||
ListenAddr string
|
||||
TargetAddr string
|
||||
FakeAddr string
|
||||
}
|
||||
|
||||
var (
|
||||
serverParams *ServerParam
|
||||
serverCmd = &cobra.Command{
|
||||
Use: "server",
|
||||
Short: "Server mode",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
server := shadow.NewServer(serverParams.ListenAddr, serverParams.TargetAddr, serverParams.FakeAddr)
|
||||
server.Start()
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
serverParams = &ServerParam{}
|
||||
serverCmd.Flags().StringVarP(&serverParams.ListenAddr, "listen", "l", "0.0.0.0:443", "Listen address and port")
|
||||
serverCmd.Flags().StringVarP(&serverParams.TargetAddr, "target", "t", "", "target address and port to be proxied")
|
||||
serverCmd.Flags().StringVarP(&serverParams.FakeAddr, "faddr", "f", "", "Address and port of server to make TLS")
|
||||
serverCmd.MarkFlagRequired("listen")
|
||||
serverCmd.MarkFlagRequired("target")
|
||||
serverCmd.MarkFlagRequired("faddr")
|
||||
rootCmd.AddCommand(serverCmd)
|
||||
}
|
13
go.mod
Normal file
13
go.mod
Normal file
@ -0,0 +1,13 @@
|
||||
module shadowTLS
|
||||
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/spf13/cobra v1.5.0
|
||||
github.com/xtaci/smux v1.5.16
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
)
|
12
go.sum
Normal file
12
go.sum
Normal file
@ -0,0 +1,12 @@
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
|
||||
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/xtaci/smux v1.5.16 h1:FBPYOkW8ZTjLKUM4LI4xnnuuDC8CQ/dB04HD519WoEk=
|
||||
github.com/xtaci/smux v1.5.16/go.mod h1:OMlQbT5vcgl2gb49mFkYo6SMf+zP3rcjcwQz7ZU7IGY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
8
main.go
Normal file
8
main.go
Normal file
@ -0,0 +1,8 @@
|
||||
package main
|
||||
|
||||
import "shadowTLS/cmd"
|
||||
|
||||
func main() {
|
||||
|
||||
cmd.Execute()
|
||||
}
|
51
shadow/client.go
Normal file
51
shadow/client.go
Normal file
@ -0,0 +1,51 @@
|
||||
package shadow
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
ListenAddress string
|
||||
ServerAddress string
|
||||
FakeAddressSNI string
|
||||
}
|
||||
|
||||
func NewClient(listenAddress string, serverAddress string, fakeAddressSNI string) *Client {
|
||||
client := &Client{
|
||||
ListenAddress: listenAddress,
|
||||
ServerAddress: serverAddress,
|
||||
FakeAddressSNI: fakeAddressSNI,
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
func (c *Client) Start() {
|
||||
bridge := NewTLSBridge(c.ServerAddress, c.FakeAddressSNI)
|
||||
|
||||
listen, err := net.Listen("tcp", c.ListenAddress)
|
||||
if err != nil {
|
||||
fmt.Printf("[Client] Start client error: %v\n", err)
|
||||
return
|
||||
}
|
||||
defer listen.Close()
|
||||
fmt.Printf("[Client] Listening at:%v\n", c.ListenAddress)
|
||||
for {
|
||||
conn, err := listen.Accept()
|
||||
if err != nil {
|
||||
fmt.Printf("[Client] accept error: %v\n", err)
|
||||
continue
|
||||
}
|
||||
|
||||
stream := bridge.GetStream()
|
||||
if stream == nil {
|
||||
conn.Close()
|
||||
fmt.Printf("[Client] connect to server error: %v\n", err)
|
||||
continue
|
||||
}
|
||||
fmt.Printf("[Client] New TCP connection: %v <-> %v \n", conn.LocalAddr().String(), conn.RemoteAddr().String())
|
||||
go io.Copy(conn, stream)
|
||||
go io.Copy(stream, conn)
|
||||
}
|
||||
}
|
128
shadow/client_test.go
Normal file
128
shadow/client_test.go
Normal file
@ -0,0 +1,128 @@
|
||||
package shadow
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/xtaci/smux"
|
||||
"io"
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
listen, err := net.Listen("tcp", "0.0.0.0:11222")
|
||||
if err != nil {
|
||||
fmt.Printf("Start server failed : %v\n", err)
|
||||
return
|
||||
}
|
||||
defer listen.Close()
|
||||
for {
|
||||
conn, err := listen.Accept()
|
||||
if err != nil {
|
||||
fmt.Printf("Accept error: %v\n", err)
|
||||
continue
|
||||
}
|
||||
fmt.Println("A")
|
||||
go handler(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func handler(conn net.Conn) {
|
||||
|
||||
fakeConn, err := net.Dial("tcp", "127.0.0.1:5900")
|
||||
if err != nil {
|
||||
fmt.Printf("Dial fake failed : %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
go io.Copy(fakeConn, conn)
|
||||
go io.Copy(conn, fakeConn)
|
||||
}
|
||||
|
||||
func TestSmuxServer(t *testing.T) {
|
||||
listen, err := net.Listen("tcp", "0.0.0.0:7556")
|
||||
if err != nil {
|
||||
fmt.Printf("Start server failed : %v\n", err)
|
||||
return
|
||||
}
|
||||
defer listen.Close()
|
||||
for {
|
||||
conn, err := listen.Accept()
|
||||
if err != nil {
|
||||
fmt.Printf("Accept error: %v\n", err)
|
||||
continue
|
||||
}
|
||||
session, err := smux.Server(conn, nil)
|
||||
if err != nil {
|
||||
fmt.Printf("smux error: %v\n", err)
|
||||
continue
|
||||
}
|
||||
|
||||
go func() {
|
||||
for {
|
||||
stream, err := session.AcceptStream()
|
||||
if err != nil {
|
||||
fmt.Printf("AcceptStream error: %v\n", err)
|
||||
continue
|
||||
}
|
||||
fmt.Println("A")
|
||||
go handlerMuxTest(stream)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestSmuxClient(t *testing.T) {
|
||||
listen, err := net.Listen("tcp", "0.0.0.0:11222")
|
||||
if err != nil {
|
||||
fmt.Printf("Start server failed : %v\n", err)
|
||||
return
|
||||
}
|
||||
defer listen.Close()
|
||||
|
||||
smuxConn, err := net.Dial("tcp", "127.0.0.1:7556")
|
||||
if err != nil {
|
||||
fmt.Printf("Start smuxConn failed : %v\n", err)
|
||||
return
|
||||
}
|
||||
session, err := smux.Client(smuxConn, nil)
|
||||
if err != nil {
|
||||
fmt.Printf("Start smux.Client failed : %v\n", err)
|
||||
return
|
||||
}
|
||||
for {
|
||||
conn, err := listen.Accept()
|
||||
if err != nil {
|
||||
fmt.Printf("Accept error: %v\n", err)
|
||||
continue
|
||||
}
|
||||
fmt.Println("A")
|
||||
|
||||
stream, err := session.OpenStream()
|
||||
if err != nil {
|
||||
fmt.Printf("OpenStream error: %v\n", err)
|
||||
continue
|
||||
|
||||
}
|
||||
go io.Copy(conn, stream)
|
||||
go io.Copy(stream, conn)
|
||||
}
|
||||
}
|
||||
|
||||
func handlerMuxTest(conn *smux.Stream) {
|
||||
|
||||
fakeConn, err := net.Dial("tcp", "127.0.0.1:5900")
|
||||
if err != nil {
|
||||
fmt.Printf("Dial fake failed : %v\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Println("UUUUUUUUUUUUUU")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
go io.Copy(fakeConn, conn)
|
||||
go io.Copy(conn, fakeConn)
|
||||
}
|
127
shadow/server.go
Normal file
127
shadow/server.go
Normal file
@ -0,0 +1,127 @@
|
||||
package shadow
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/xtaci/smux"
|
||||
"io"
|
||||
"net"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
ListenAddress string
|
||||
TargetAddress string
|
||||
FakeAddress string
|
||||
}
|
||||
|
||||
func NewServer(listenAddress string, targetAddress string, fakeAddress string) *Server {
|
||||
server := &Server{
|
||||
ListenAddress: listenAddress,
|
||||
TargetAddress: targetAddress,
|
||||
FakeAddress: fakeAddress,
|
||||
}
|
||||
return server
|
||||
}
|
||||
|
||||
func (s *Server) Start() {
|
||||
listen, err := net.Listen("tcp", s.ListenAddress)
|
||||
if err != nil {
|
||||
fmt.Printf("[Server] Start server error: %v\n", err)
|
||||
return
|
||||
}
|
||||
defer listen.Close()
|
||||
fmt.Printf("[Server] Listening at:%v\n", s.ListenAddress)
|
||||
for {
|
||||
conn, err := listen.Accept()
|
||||
if err != nil {
|
||||
fmt.Printf("[Server] Accept error: %v\n", err)
|
||||
continue
|
||||
}
|
||||
go handler(conn, s.TargetAddress, s.FakeAddress)
|
||||
}
|
||||
}
|
||||
|
||||
func handler(conn net.Conn, targetAddress string, fakeAddress string) {
|
||||
|
||||
//Process fake TLS handshake
|
||||
fmt.Println("[Server] Perform handshake")
|
||||
fakeConn, err := net.Dial("tcp", fakeAddress)
|
||||
if err != nil {
|
||||
fmt.Printf("[Server] Dial fake error : %v\n", err)
|
||||
return
|
||||
}
|
||||
waitCh := make(chan int, 2)
|
||||
|
||||
go processHandshake(conn, fakeConn, waitCh)
|
||||
go processHandshake(fakeConn, conn, waitCh)
|
||||
|
||||
<-waitCh
|
||||
<-waitCh
|
||||
|
||||
//Process real tcp connection
|
||||
session, err := smux.Server(conn, nil)
|
||||
if err != nil {
|
||||
fmt.Printf("[Server] smux error: %v\n", err)
|
||||
return
|
||||
}
|
||||
for {
|
||||
stream, err := session.AcceptStream()
|
||||
if err != nil {
|
||||
fmt.Printf("[Server] AcceptStream error: %v\n", err)
|
||||
break
|
||||
}
|
||||
go handlerMux(stream, targetAddress)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func processHandshake(src net.Conn, dst net.Conn, waitCh chan int) {
|
||||
buf := make([]byte, 32*1024)
|
||||
for {
|
||||
nr, er := src.Read(buf)
|
||||
if nr > 0 {
|
||||
|
||||
header := ParseAndVerifyTLSHeader(buf[0:nr])
|
||||
nw, ew := dst.Write(buf[0:nr])
|
||||
if header != nil && header.Type == ChangeCipherSpec {
|
||||
fmt.Println("[Server] handshake complete")
|
||||
dst.Close()
|
||||
break
|
||||
}
|
||||
if nw < 0 || nr < nw {
|
||||
nw = 0
|
||||
if ew == nil {
|
||||
//fmt.Printf("ERR1 %v \n", ew)
|
||||
}
|
||||
}
|
||||
if ew != nil {
|
||||
//fmt.Printf("ERR2 %v \n", ew)
|
||||
break
|
||||
}
|
||||
if nr != nw {
|
||||
//fmt.Printf("ERR3 %v \n", "shortwrite")
|
||||
break
|
||||
}
|
||||
}
|
||||
if er != nil {
|
||||
if er != io.EOF {
|
||||
//fmt.Printf("ERR4 %v \n", er)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
waitCh <- 1
|
||||
}
|
||||
|
||||
func handlerMux(conn *smux.Stream, targetAddress string) {
|
||||
|
||||
realConnection, err := net.Dial("tcp", targetAddress)
|
||||
if err != nil {
|
||||
fmt.Printf("[Server] Dial target error : %v\n", err)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
go io.Copy(realConnection, conn)
|
||||
go io.Copy(conn, realConnection)
|
||||
}
|
70
shadow/tls_bridge.go
Normal file
70
shadow/tls_bridge.go
Normal file
@ -0,0 +1,70 @@
|
||||
package shadow
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"github.com/xtaci/smux"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type TLSBridge struct {
|
||||
session *smux.Session
|
||||
locker sync.Mutex
|
||||
serverAddress string
|
||||
fakeAddressSNI string
|
||||
}
|
||||
|
||||
func NewTLSBridge(serverAddress string, fakeAddressSNI string) *TLSBridge {
|
||||
t := &TLSBridge{
|
||||
session: nil,
|
||||
locker: sync.Mutex{},
|
||||
serverAddress: serverAddress,
|
||||
fakeAddressSNI: fakeAddressSNI,
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *TLSBridge) dial() error {
|
||||
if t.session != nil {
|
||||
t.session.Close()
|
||||
}
|
||||
dial, err := tls.DialWithDialer(&net.Dialer{
|
||||
Timeout: time.Second * 5,
|
||||
}, "tcp", t.serverAddress, &tls.Config{
|
||||
ServerName: t.fakeAddressSNI,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = dial.Handshake()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
session, err := smux.Client(dial.NetConn(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.session = session
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TLSBridge) GetStream() *smux.Stream {
|
||||
t.locker.Lock()
|
||||
defer t.locker.Unlock()
|
||||
|
||||
if t.session == nil {
|
||||
err := t.dial()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
openStream, err := t.session.OpenStream()
|
||||
if err != nil {
|
||||
t.session.Close()
|
||||
t.session = nil
|
||||
}
|
||||
return openStream
|
||||
|
||||
}
|
87
shadow/tls_util.go
Normal file
87
shadow/tls_util.go
Normal file
@ -0,0 +1,87 @@
|
||||
package shadow
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
const (
|
||||
RecordHeaderLen = 5
|
||||
|
||||
ChangeCipherSpec = 0x14
|
||||
EncryptedAlert = 0x15
|
||||
Handshake = 0x16
|
||||
AppData = 0x17
|
||||
|
||||
VersionTLS10 = 0x0301
|
||||
VersionTLS11 = 0x0302
|
||||
VersionTLS12 = 0x0303
|
||||
VersionTLS13 = 0x0304
|
||||
|
||||
ServerHello = 2
|
||||
ClientHello = 1
|
||||
)
|
||||
|
||||
type TLSHeader struct {
|
||||
Type uint8
|
||||
Version uint16
|
||||
Length int
|
||||
HandshakeType uint8
|
||||
}
|
||||
|
||||
func (t *TLSHeader) toString() string {
|
||||
if t == nil {
|
||||
return "nul"
|
||||
}
|
||||
desc := ""
|
||||
switch t.Type {
|
||||
case Handshake:
|
||||
desc += "Type=handshake;"
|
||||
switch t.HandshakeType {
|
||||
case ClientHello:
|
||||
desc += "HandshakeType=ClientHello;"
|
||||
break
|
||||
case ServerHello:
|
||||
desc += "HandshakeType=ServerHello;"
|
||||
break
|
||||
}
|
||||
break
|
||||
case ChangeCipherSpec:
|
||||
desc += "Type=ChangeCipherSpec;"
|
||||
break
|
||||
case EncryptedAlert:
|
||||
desc += "Type=EncryptedAlert;"
|
||||
break
|
||||
case AppData:
|
||||
desc += "Type=AppData;"
|
||||
break
|
||||
}
|
||||
return desc
|
||||
}
|
||||
|
||||
func ParseAndVerifyTLSHeader(data []byte) *TLSHeader {
|
||||
if len(data) < RecordHeaderLen {
|
||||
return nil
|
||||
}
|
||||
header := &TLSHeader{
|
||||
Type: data[0],
|
||||
Version: binary.BigEndian.Uint16(data[1:3]),
|
||||
Length: int(binary.BigEndian.Uint16(data[3:5])),
|
||||
}
|
||||
//Check type
|
||||
if header.Type != Handshake && header.Type != AppData && header.Type != EncryptedAlert && header.Type != ChangeCipherSpec {
|
||||
return nil
|
||||
}
|
||||
//Check version
|
||||
if header.Version != VersionTLS10 && header.Version != VersionTLS11 && header.Version != VersionTLS12 && header.Version != VersionTLS13 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if header.Type == Handshake {
|
||||
header.HandshakeType = data[5]
|
||||
//Check Handshake type
|
||||
if header.HandshakeType != ServerHello && header.HandshakeType != ClientHello {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return header
|
||||
}
|
1
startCmd.bat
Normal file
1
startCmd.bat
Normal file
@ -0,0 +1 @@
|
||||
start
|
Loading…
Reference in New Issue
Block a user