mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-07-19 22:08:07 +03:00
Add Snell protocol. Refactor MASQUE HTTP/2, Fair Queue. Update XHTTP, OpenVPN, Sudoku, Fallback. Fixes
This commit is contained in:
154
transport/simple-obfs/tls_server.go
Normal file
154
transport/simple-obfs/tls_server.go
Normal file
@@ -0,0 +1,154 @@
|
||||
package obfs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
B "github.com/sagernet/sing/common/buf"
|
||||
)
|
||||
|
||||
// TLSObfsServer is the server side of the shadowsocks tls simple-obfs implementation.
|
||||
type TLSObfsServer struct {
|
||||
net.Conn
|
||||
remain int
|
||||
firstRequest bool
|
||||
sessionTicketDone bool
|
||||
firstResponse bool
|
||||
}
|
||||
|
||||
func (tos *TLSObfsServer) read(b []byte, discardN int) (int, error) {
|
||||
buf := B.Get(discardN)
|
||||
_, err := io.ReadFull(tos.Conn, buf)
|
||||
B.Put(buf)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
sizeBuf := make([]byte, 2)
|
||||
_, err = io.ReadFull(tos.Conn, sizeBuf)
|
||||
if err != nil {
|
||||
return 0, nil
|
||||
}
|
||||
length := int(binary.BigEndian.Uint16(sizeBuf))
|
||||
if length > len(b) {
|
||||
n, err := tos.Conn.Read(b)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
tos.remain = length - n
|
||||
return n, nil
|
||||
}
|
||||
return io.ReadFull(tos.Conn, b[:length])
|
||||
}
|
||||
|
||||
// skipOtherExts skips SNI & other TLS extensions.
|
||||
func (tos *TLSObfsServer) skipOtherExts() error {
|
||||
buf := make([]byte, 256)
|
||||
_, err := tos.read(buf, 7)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.ReadFull(tos.Conn, buf[:4*16+2])
|
||||
return err
|
||||
}
|
||||
|
||||
func (tos *TLSObfsServer) Read(b []byte) (int, error) {
|
||||
if tos.remain > 0 {
|
||||
length := tos.remain
|
||||
if length > len(b) {
|
||||
length = len(b)
|
||||
}
|
||||
n, err := io.ReadFull(tos.Conn, b[:length])
|
||||
tos.remain -= n
|
||||
return n, err
|
||||
}
|
||||
if tos.firstRequest {
|
||||
tos.firstRequest = false
|
||||
return tos.read(b, 9*16-4)
|
||||
}
|
||||
if !tos.sessionTicketDone {
|
||||
tos.sessionTicketDone = true
|
||||
err := tos.skipOtherExts()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
return tos.read(b, 3)
|
||||
}
|
||||
|
||||
func (tos *TLSObfsServer) Write(b []byte) (int, error) {
|
||||
length := len(b)
|
||||
for i := 0; i < length; i += chunkSize {
|
||||
end := i + chunkSize
|
||||
if end > length {
|
||||
end = length
|
||||
}
|
||||
n, err := tos.write(b[i:end])
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
return length, nil
|
||||
}
|
||||
|
||||
func (tos *TLSObfsServer) write(b []byte) (int, error) {
|
||||
if tos.firstResponse {
|
||||
serverHello := makeServerHello(b)
|
||||
_, err := tos.Conn.Write(serverHello)
|
||||
tos.firstResponse = false
|
||||
return len(b), err
|
||||
}
|
||||
buf := B.NewSize(5 + len(b))
|
||||
defer buf.Release()
|
||||
buf.Write([]byte{0x17, 0x03, 0x03})
|
||||
binary.Write(buf, binary.BigEndian, uint16(len(b)))
|
||||
buf.Write(b)
|
||||
_, err := tos.Conn.Write(buf.Bytes())
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
func (tos *TLSObfsServer) Upstream() any {
|
||||
return tos.Conn
|
||||
}
|
||||
|
||||
// NewTLSObfsServer returns a server-side TLS SimpleObfs.
|
||||
func NewTLSObfsServer(conn net.Conn) net.Conn {
|
||||
return &TLSObfsServer{
|
||||
Conn: conn,
|
||||
firstRequest: true,
|
||||
firstResponse: true,
|
||||
}
|
||||
}
|
||||
|
||||
func makeServerHello(data []byte) []byte {
|
||||
randBytes := make([]byte, 28)
|
||||
sessionId := make([]byte, 32)
|
||||
rand.Read(randBytes)
|
||||
rand.Read(sessionId)
|
||||
buf := &bytes.Buffer{}
|
||||
buf.WriteByte(0x16)
|
||||
binary.Write(buf, binary.BigEndian, uint16(0x0301))
|
||||
binary.Write(buf, binary.BigEndian, uint16(91))
|
||||
buf.Write([]byte{2, 0, 0, 87, 0x03, 0x03})
|
||||
binary.Write(buf, binary.BigEndian, uint32(time.Now().Unix()))
|
||||
buf.Write(randBytes)
|
||||
buf.WriteByte(32)
|
||||
buf.Write(sessionId)
|
||||
buf.Write([]byte{0xcc, 0xa8})
|
||||
buf.WriteByte(0)
|
||||
buf.Write([]byte{0x00, 0x00})
|
||||
buf.Write([]byte{0xff, 0x01, 0x00, 0x01, 0x00})
|
||||
buf.Write([]byte{0x00, 0x17, 0x00, 0x00})
|
||||
buf.Write([]byte{0x00, 0x0b, 0x00, 0x02, 0x01, 0x00})
|
||||
buf.Write([]byte{0x14, 0x03, 0x03, 0x00, 0x01, 0x01})
|
||||
buf.Write([]byte{0x16, 0x03, 0x03})
|
||||
binary.Write(buf, binary.BigEndian, uint16(len(data)))
|
||||
buf.Write(data)
|
||||
return buf.Bytes()
|
||||
}
|
||||
Reference in New Issue
Block a user