mirror of https://github.com/cbeuw/Cloak
Barely working
This commit is contained in:
parent
ae30ed6ba4
commit
b9f2aa4ed0
|
|
@ -31,7 +31,7 @@ func pipe(dst io.ReadWriteCloser, src io.ReadWriteCloser) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This establishes a connection with ckserver and performs a handshake
|
// This establishes a connection with ckserver and performs a handshake
|
||||||
func makeRemoteConn(sta *client.State) net.Conn {
|
func makeRemoteConn(sta *client.State) (net.Conn, error) {
|
||||||
|
|
||||||
d := net.Dialer{Control: protector}
|
d := net.Dialer{Control: protector}
|
||||||
|
|
||||||
|
|
@ -39,12 +39,12 @@ func makeRemoteConn(sta *client.State) net.Conn {
|
||||||
remoteConn, err := d.Dial("tcp", sta.SS_REMOTE_HOST+":"+sta.SS_REMOTE_PORT)
|
remoteConn, err := d.Dial("tcp", sta.SS_REMOTE_HOST+":"+sta.SS_REMOTE_PORT)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Connecting to remote: %v\n", err)
|
log.Printf("Connecting to remote: %v\n", err)
|
||||||
return nil
|
return nil, err
|
||||||
}
|
}
|
||||||
_, err = remoteConn.Write(clientHello)
|
_, err = remoteConn.Write(clientHello)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Sending ClientHello: %v\n", err)
|
log.Printf("Sending ClientHello: %v\n", err)
|
||||||
return nil
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Three discarded messages: ServerHello, ChangeCipherSpec and Finished
|
// Three discarded messages: ServerHello, ChangeCipherSpec and Finished
|
||||||
|
|
@ -53,7 +53,7 @@ func makeRemoteConn(sta *client.State) net.Conn {
|
||||||
_, err = util.ReadTillDrain(remoteConn, discardBuf)
|
_, err = util.ReadTillDrain(remoteConn, discardBuf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Reading discarded message %v: %v\n", c, err)
|
log.Printf("Reading discarded message %v: %v\n", c, err)
|
||||||
return nil
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,10 +61,10 @@ func makeRemoteConn(sta *client.State) net.Conn {
|
||||||
_, err = remoteConn.Write(reply)
|
_, err = remoteConn.Write(reply)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Sending reply to remote: %v\n", err)
|
log.Printf("Sending reply to remote: %v\n", err)
|
||||||
return nil
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return remoteConn
|
return remoteConn, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -134,7 +134,10 @@ func main() {
|
||||||
log.Fatal("TicketTimeHint cannot be empty or 0")
|
log.Fatal("TicketTimeHint cannot be empty or 0")
|
||||||
}
|
}
|
||||||
|
|
||||||
initRemoteConn := makeRemoteConn(sta)
|
initRemoteConn, err := makeRemoteConn(sta)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to establish connection to remote: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
obfs := util.MakeObfs(sta.SID)
|
obfs := util.MakeObfs(sta.SID)
|
||||||
deobfs := util.MakeDeobfs(sta.SID)
|
deobfs := util.MakeDeobfs(sta.SID)
|
||||||
|
|
@ -143,7 +146,11 @@ func main() {
|
||||||
|
|
||||||
for i := 0; i < sta.NumConn-1; i++ {
|
for i := 0; i < sta.NumConn-1; i++ {
|
||||||
go func() {
|
go func() {
|
||||||
conn := makeRemoteConn(sta)
|
conn, err := makeRemoteConn(sta)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to establish new connections to remote: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
sesh.AddConnection(conn)
|
sesh.AddConnection(conn)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
@ -159,10 +166,17 @@ func main() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
|
data := make([]byte, 10240)
|
||||||
|
i, err := io.ReadAtLeast(ssConn, data, 1)
|
||||||
|
if err != nil {
|
||||||
|
ssConn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
stream, err := sesh.OpenStream()
|
stream, err := sesh.OpenStream()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ssConn.Close()
|
ssConn.Close()
|
||||||
}
|
}
|
||||||
|
stream.Write(data[:i])
|
||||||
go pipe(ssConn, stream)
|
go pipe(ssConn, stream)
|
||||||
pipe(stream, ssConn)
|
pipe(stream, ssConn)
|
||||||
}()
|
}()
|
||||||
|
|
|
||||||
|
|
@ -89,11 +89,11 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
|
||||||
go func() {
|
go func() {
|
||||||
var arrSID [32]byte
|
var arrSID [32]byte
|
||||||
copy(arrSID[:], SID)
|
copy(arrSID[:], SID)
|
||||||
sesh := sta.GetSession(arrSID)
|
var sesh *mux.Session
|
||||||
if sesh == nil {
|
if sesh = sta.GetSession(arrSID); sesh != nil {
|
||||||
sesh.AddConnection(conn)
|
sesh.AddConnection(conn)
|
||||||
} else {
|
} else {
|
||||||
sesh := mux.MakeSession(0, conn, util.MakeObfs(SID), util.MakeDeobfs(SID), util.ReadTillDrain)
|
sesh = mux.MakeSession(0, conn, util.MakeObfs(SID), util.MakeDeobfs(SID), util.ReadTillDrain)
|
||||||
sta.PutSession(arrSID, sesh)
|
sta.PutSession(arrSID, sesh)
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
|
|
@ -166,6 +166,7 @@ func main() {
|
||||||
SS_REMOTE_PORT: remotePort,
|
SS_REMOTE_PORT: remotePort,
|
||||||
Now: time.Now,
|
Now: time.Now,
|
||||||
UsedRandom: map[[32]byte]int{},
|
UsedRandom: map[[32]byte]int{},
|
||||||
|
Sessions: map[[32]byte]*mux.Session{},
|
||||||
}
|
}
|
||||||
err := sta.ParseConfig(pluginOpts)
|
err := sta.ParseConfig(pluginOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"ServerName":"www.bing.com",
|
"ServerName":"www.bing.com",
|
||||||
"Key":"UNhY4JhezH9gQYqvDMWrWH9CwlcKiECVqejMrND2VFwEOF8c8XRX8iYVdjKW2BAfym2zppExMPteovDB/Q8phdD53FnH39tQ1daaVLn9+FIGOAdk+UZZ2aOt5jSK638YPg==",
|
"Key":"UNhY4JhezH9gQYqvDMWrWH9CwlcKiECVqejMrND2VFwEOF8c8XRX8iYVdjKW2BAfym2zppExMPteovDB/Q8phdD53FnH39tQ1daaVLn9+FIGOAdk+UZZ2aOt5jSK638YPg==",
|
||||||
"TicketTimeHint":3600,
|
"TicketTimeHint":3600,
|
||||||
"Browser":"chrome"
|
"NumConn":4,
|
||||||
|
"MaskBrowser":"chrome"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ func (sta *State) ParseConfig(conf string) (err error) {
|
||||||
sta.ServerName = preParse.ServerName
|
sta.ServerName = preParse.ServerName
|
||||||
sta.TicketTimeHint = preParse.TicketTimeHint
|
sta.TicketTimeHint = preParse.TicketTimeHint
|
||||||
sta.MaskBrowser = preParse.MaskBrowser
|
sta.MaskBrowser = preParse.MaskBrowser
|
||||||
|
sta.NumConn = preParse.NumConn
|
||||||
sid, pub, err := parseKey(preParse.Key)
|
sid, pub, err := parseKey(preParse.Key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("Failed to parse Key: " + err.Error())
|
return errors.New("Failed to parse Key: " + err.Error())
|
||||||
|
|
|
||||||
|
|
@ -53,43 +53,49 @@ func (sh *sorterHeap) Pop() interface{} {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stream) recvNewFrame(f *Frame) {
|
func (s *Stream) recvNewFrame() {
|
||||||
// For the ease of demonstration, assume seq is uint8, i.e. it wraps around after 255
|
for {
|
||||||
fs := &frameNode{
|
f := <-s.newFrameCh
|
||||||
f.Seq,
|
if f == nil {
|
||||||
0,
|
continue
|
||||||
f,
|
}
|
||||||
}
|
// For the ease of demonstration, assume seq is uint8, i.e. it wraps around after 255
|
||||||
|
fs := &frameNode{
|
||||||
// TODO: if a malicious client resend a previously sent seq number, what will happen?
|
f.Seq,
|
||||||
if fs.seq < s.nextRecvSeq {
|
0,
|
||||||
// e.g. we are on rev=0 (wrap has not happened yet)
|
f,
|
||||||
// and we get the order of recv as 253 254 0 1
|
|
||||||
// after 254, nextN should be 255, but 0 is received and 0 < 255
|
|
||||||
// now 0 should have a trueSeq of 256
|
|
||||||
if !s.wrapMode {
|
|
||||||
// wrapMode is true when the latest seq is wrapped but nextN is not
|
|
||||||
s.wrapMode = true
|
|
||||||
}
|
}
|
||||||
fs.trueSeq = uint64(2<<16*(s.rev+1)) + uint64(fs.seq) + 1
|
|
||||||
// +1 because wrapped 0 should have trueSeq of 256 instead of 255
|
|
||||||
// when this bit was run on 1, the trueSeq of 1 would become 256
|
|
||||||
} else {
|
|
||||||
fs.trueSeq = uint64(2<<16*s.rev) + uint64(fs.seq)
|
|
||||||
// when this bit was run on 255, the trueSeq of 255 would be 255
|
|
||||||
}
|
|
||||||
heap.Push(&s.sh, fs)
|
|
||||||
|
|
||||||
// Keep popping from the heap until empty or to the point that the wanted seq was not received
|
// TODO: if a malicious client resend a previously sent seq number, what will happen?
|
||||||
for len(s.sh) > 0 && s.sh[0].seq == s.nextRecvSeq {
|
if fs.seq < s.nextRecvSeq {
|
||||||
|
// e.g. we are on rev=0 (wrap has not happened yet)
|
||||||
|
// and we get the order of recv as 253 254 0 1
|
||||||
|
// after 254, nextN should be 255, but 0 is received and 0 < 255
|
||||||
|
// now 0 should have a trueSeq of 256
|
||||||
|
if !s.wrapMode {
|
||||||
|
// wrapMode is true when the latest seq is wrapped but nextN is not
|
||||||
|
s.wrapMode = true
|
||||||
|
}
|
||||||
|
fs.trueSeq = uint64(2<<16*(s.rev+1)) + uint64(fs.seq) + 1
|
||||||
|
// +1 because wrapped 0 should have trueSeq of 256 instead of 255
|
||||||
|
// when this bit was run on 1, the trueSeq of 1 would become 256
|
||||||
|
} else {
|
||||||
|
fs.trueSeq = uint64(2<<16*s.rev) + uint64(fs.seq)
|
||||||
|
// when this bit was run on 255, the trueSeq of 255 would be 255
|
||||||
|
}
|
||||||
|
heap.Push(&s.sh, fs)
|
||||||
|
|
||||||
s.sortedBufCh <- heap.Pop(&s.sh).(*frameNode).frame.Payload
|
// Keep popping from the heap until empty or to the point that the wanted seq was not received
|
||||||
|
for len(s.sh) > 0 && s.sh[0].seq == s.nextRecvSeq {
|
||||||
|
|
||||||
s.nextRecvSeq += 1
|
s.sortedBufCh <- heap.Pop(&s.sh).(*frameNode).frame.Payload
|
||||||
if s.nextRecvSeq == 0 {
|
|
||||||
// when nextN is wrapped, wrapMode becomes false and rev+1
|
s.nextRecvSeq += 1
|
||||||
s.rev += 1
|
if s.nextRecvSeq == 0 {
|
||||||
s.wrapMode = false
|
// when nextN is wrapped, wrapMode becomes false and rev+1
|
||||||
|
s.rev += 1
|
||||||
|
s.wrapMode = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package multiplex
|
package multiplex
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
@ -49,13 +50,12 @@ func MakeSession(id int, conn net.Conn, obfs func(*Frame) []byte, deobfs func([]
|
||||||
obfs: obfs,
|
obfs: obfs,
|
||||||
deobfs: deobfs,
|
deobfs: deobfs,
|
||||||
obfsedReader: obfsedReader,
|
obfsedReader: obfsedReader,
|
||||||
nextStreamID: 0,
|
nextStreamID: 1,
|
||||||
streams: make(map[uint32]*Stream),
|
streams: make(map[uint32]*Stream),
|
||||||
acceptCh: make(chan *Stream, acceptBacklog),
|
acceptCh: make(chan *Stream, acceptBacklog),
|
||||||
closeQCh: make(chan uint32, closeBacklog),
|
closeQCh: make(chan uint32, closeBacklog),
|
||||||
}
|
}
|
||||||
sesh.sb = makeSwitchboard(conn, sesh)
|
sesh.sb = makeSwitchboard(conn, sesh)
|
||||||
sesh.sb.run()
|
|
||||||
return sesh
|
return sesh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,6 +80,7 @@ func (sesh *Session) OpenStream() (*Stream, error) {
|
||||||
func (sesh *Session) AcceptStream() (*Stream, error) {
|
func (sesh *Session) AcceptStream() (*Stream, error) {
|
||||||
stream := <-sesh.acceptCh
|
stream := <-sesh.acceptCh
|
||||||
return stream, nil
|
return stream, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sesh *Session) delStream(id uint32) {
|
func (sesh *Session) delStream(id uint32) {
|
||||||
|
|
@ -101,7 +102,13 @@ func (sesh *Session) getStream(id uint32) *Stream {
|
||||||
return sesh.streams[id]
|
return sesh.streams[id]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sesh *Session) addStream(id uint32) {
|
// addStream is used when the remote opened a new stream and we got notified
|
||||||
|
func (sesh *Session) addStream(id uint32) *Stream {
|
||||||
|
log.Printf("Adding stream %v", id)
|
||||||
stream := makeStream(id, sesh)
|
stream := makeStream(id, sesh)
|
||||||
|
sesh.streamsM.Lock()
|
||||||
|
sesh.streams[id] = stream
|
||||||
|
sesh.streamsM.Unlock()
|
||||||
sesh.acceptCh <- stream
|
sesh.acceptCh <- stream
|
||||||
|
return stream
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
readBuffer = 10240
|
readBuffer = 102400
|
||||||
)
|
)
|
||||||
|
|
||||||
type Stream struct {
|
type Stream struct {
|
||||||
|
|
@ -25,6 +25,7 @@ type Stream struct {
|
||||||
sh sorterHeap
|
sh sorterHeap
|
||||||
wrapMode bool
|
wrapMode bool
|
||||||
|
|
||||||
|
newFrameCh chan *Frame
|
||||||
sortedBufCh chan []byte
|
sortedBufCh chan []byte
|
||||||
|
|
||||||
nextSendSeqM sync.Mutex
|
nextSendSeqM sync.Mutex
|
||||||
|
|
@ -36,14 +37,19 @@ type Stream struct {
|
||||||
|
|
||||||
func makeStream(id uint32, sesh *Session) *Stream {
|
func makeStream(id uint32, sesh *Session) *Stream {
|
||||||
stream := &Stream{
|
stream := &Stream{
|
||||||
id: id,
|
id: id,
|
||||||
session: sesh,
|
session: sesh,
|
||||||
|
die: make(chan struct{}),
|
||||||
|
sh: []*frameNode{},
|
||||||
|
newFrameCh: make(chan *Frame, 1024),
|
||||||
|
sortedBufCh: make(chan []byte, readBuffer),
|
||||||
}
|
}
|
||||||
|
go stream.recvNewFrame()
|
||||||
return stream
|
return stream
|
||||||
}
|
}
|
||||||
|
|
||||||
func (stream *Stream) Read(buf []byte) (n int, err error) {
|
func (stream *Stream) Read(buf []byte) (n int, err error) {
|
||||||
if len(buf) == 0 {
|
if len(buf) != 0 {
|
||||||
select {
|
select {
|
||||||
case <-stream.die:
|
case <-stream.die:
|
||||||
return 0, errors.New(errBrokenPipe)
|
return 0, errors.New(errBrokenPipe)
|
||||||
|
|
@ -79,8 +85,8 @@ func (stream *Stream) Write(in []byte) (n int, err error) {
|
||||||
StreamID: stream.id,
|
StreamID: stream.id,
|
||||||
Seq: stream.nextSendSeq,
|
Seq: stream.nextSendSeq,
|
||||||
ClosingStreamID: closingID,
|
ClosingStreamID: closingID,
|
||||||
|
Payload: in,
|
||||||
}
|
}
|
||||||
copy(f.Payload, in)
|
|
||||||
|
|
||||||
stream.nextSendSeqM.Lock()
|
stream.nextSendSeqM.Lock()
|
||||||
stream.nextSendSeq += 1
|
stream.nextSendSeq += 1
|
||||||
|
|
@ -103,7 +109,6 @@ func (stream *Stream) Close() error {
|
||||||
stream.closing = true
|
stream.closing = true
|
||||||
stream.session.delStream(stream.id)
|
stream.session.delStream(stream.id)
|
||||||
close(stream.die)
|
close(stream.die)
|
||||||
close(stream.sortedBufCh)
|
|
||||||
stream.session.closeQCh <- stream.id
|
stream.session.closeQCh <- stream.id
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
package multiplex
|
package multiplex
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
sentNotifyBacklog = 1024
|
sentNotifyBacklog = 1024
|
||||||
dispatchBacklog = 10240
|
dispatchBacklog = 102400
|
||||||
|
newConnBacklog = 8
|
||||||
)
|
)
|
||||||
|
|
||||||
type switchboard struct {
|
type switchboard struct {
|
||||||
|
|
@ -19,6 +21,7 @@ type switchboard struct {
|
||||||
sentNotifyCh chan *sentNotifier
|
sentNotifyCh chan *sentNotifier
|
||||||
dispatCh chan []byte
|
dispatCh chan []byte
|
||||||
newConnCh chan net.Conn
|
newConnCh chan net.Conn
|
||||||
|
closingCECh chan *connEnclave
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some data comes from a Stream to be sent through one of the many
|
// Some data comes from a Stream to be sent through one of the many
|
||||||
|
|
@ -51,6 +54,8 @@ func makeSwitchboard(conn net.Conn, sesh *Session) *switchboard {
|
||||||
ces: []*connEnclave{},
|
ces: []*connEnclave{},
|
||||||
sentNotifyCh: make(chan *sentNotifier, sentNotifyBacklog),
|
sentNotifyCh: make(chan *sentNotifier, sentNotifyBacklog),
|
||||||
dispatCh: make(chan []byte, dispatchBacklog),
|
dispatCh: make(chan []byte, dispatchBacklog),
|
||||||
|
newConnCh: make(chan net.Conn, newConnBacklog),
|
||||||
|
closingCECh: make(chan *connEnclave, 5),
|
||||||
}
|
}
|
||||||
ce := &connEnclave{
|
ce := &connEnclave{
|
||||||
sb: sb,
|
sb: sb,
|
||||||
|
|
@ -58,15 +63,12 @@ func makeSwitchboard(conn net.Conn, sesh *Session) *switchboard {
|
||||||
sendQueue: 0,
|
sendQueue: 0,
|
||||||
}
|
}
|
||||||
sb.ces = append(sb.ces, ce)
|
sb.ces = append(sb.ces, ce)
|
||||||
|
go sb.deplex(ce)
|
||||||
|
|
||||||
|
go sb.dispatch()
|
||||||
return sb
|
return sb
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sb *switchboard) run() {
|
|
||||||
go sb.startDispatcher()
|
|
||||||
go sb.startDeplexer()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Everytime after a remoteConn sends something, it constructs this struct
|
// Everytime after a remoteConn sends something, it constructs this struct
|
||||||
// Which is sent back to dispatch() through sentNotifyCh to tell dispatch
|
// Which is sent back to dispatch() through sentNotifyCh to tell dispatch
|
||||||
// how many bytes it has sent
|
// how many bytes it has sent
|
||||||
|
|
@ -87,7 +89,7 @@ func (ce *connEnclave) send(data []byte) {
|
||||||
|
|
||||||
// Dispatcher sends data coming from a stream to a remote connection
|
// Dispatcher sends data coming from a stream to a remote connection
|
||||||
// I used channels here because I didn't want to use mutex
|
// I used channels here because I didn't want to use mutex
|
||||||
func (sb *switchboard) startDispatcher() {
|
func (sb *switchboard) dispatch() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
// dispatCh receives data from stream.Write
|
// dispatCh receives data from stream.Write
|
||||||
|
|
@ -104,25 +106,38 @@ func (sb *switchboard) startDispatcher() {
|
||||||
sendQueue: 0,
|
sendQueue: 0,
|
||||||
}
|
}
|
||||||
sb.ces = append(sb.ces, newCe)
|
sb.ces = append(sb.ces, newCe)
|
||||||
|
go sb.deplex(newCe)
|
||||||
sort.Sort(byQ(sb.ces))
|
sort.Sort(byQ(sb.ces))
|
||||||
|
case closing := <-sb.closingCECh:
|
||||||
|
for i, ce := range sb.ces {
|
||||||
|
if closing == ce {
|
||||||
|
sb.ces = append(sb.ces[:i], sb.ces[i+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: when all connections closed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deplexer sends data coming from a remote connection to a stream
|
func (sb *switchboard) deplex(ce *connEnclave) {
|
||||||
func (sb *switchboard) startDeplexer() {
|
buf := make([]byte, 20480)
|
||||||
for _, ce := range sb.ces {
|
for {
|
||||||
go func() {
|
i, err := sb.session.obfsedReader(ce.remoteConn, buf)
|
||||||
buf := make([]byte, 20480)
|
if err != nil {
|
||||||
for {
|
log.Println(err)
|
||||||
sb.session.obfsedReader(ce.remoteConn, buf)
|
go ce.remoteConn.Close()
|
||||||
frame := sb.session.deobfs(buf)
|
sb.closingCECh <- ce
|
||||||
if !sb.session.isStream(frame.StreamID) {
|
return
|
||||||
sb.session.addStream(frame.StreamID)
|
}
|
||||||
}
|
frame := sb.session.deobfs(buf[:i])
|
||||||
sb.session.getStream(frame.ClosingStreamID).Close()
|
var stream *Stream
|
||||||
sb.session.getStream(frame.StreamID).recvNewFrame(frame)
|
if stream = sb.session.getStream(frame.StreamID); stream == nil {
|
||||||
}
|
stream = sb.session.addStream(frame.StreamID)
|
||||||
}()
|
}
|
||||||
|
if closing := sb.session.getStream(frame.ClosingStreamID); closing != nil {
|
||||||
|
closing.Close()
|
||||||
|
}
|
||||||
|
stream.newFrameCh <- frame
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import (
|
||||||
func encrypt(iv []byte, key []byte, plaintext []byte) []byte {
|
func encrypt(iv []byte, key []byte, plaintext []byte) []byte {
|
||||||
block, _ := aes.NewCipher(key)
|
block, _ := aes.NewCipher(key)
|
||||||
ciphertext := make([]byte, len(plaintext))
|
ciphertext := make([]byte, len(plaintext))
|
||||||
stream := cipher.NewCFBEncrypter(block, iv)
|
stream := cipher.NewCTR(block, iv)
|
||||||
stream.XORKeyStream(ciphertext, plaintext)
|
stream.XORKeyStream(ciphertext, plaintext)
|
||||||
return ciphertext
|
return ciphertext
|
||||||
}
|
}
|
||||||
|
|
@ -20,9 +20,8 @@ func decrypt(iv []byte, key []byte, ciphertext []byte) []byte {
|
||||||
ret := make([]byte, len(ciphertext))
|
ret := make([]byte, len(ciphertext))
|
||||||
copy(ret, ciphertext) // Because XORKeyStream is inplace, but we don't want the input to be changed
|
copy(ret, ciphertext) // Because XORKeyStream is inplace, but we don't want the input to be changed
|
||||||
block, _ := aes.NewCipher(key)
|
block, _ := aes.NewCipher(key)
|
||||||
stream := cipher.NewCFBDecrypter(block, iv)
|
stream := cipher.NewCTR(block, iv)
|
||||||
stream.XORKeyStream(ret, ret)
|
stream.XORKeyStream(ret, ret)
|
||||||
// ret is now plaintext
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,17 +32,13 @@ func MakeObfs(key []byte) func(*mux.Frame) []byte {
|
||||||
binary.BigEndian.PutUint32(header[4:8], f.Seq)
|
binary.BigEndian.PutUint32(header[4:8], f.Seq)
|
||||||
binary.BigEndian.PutUint32(header[8:12], f.ClosingStreamID)
|
binary.BigEndian.PutUint32(header[8:12], f.ClosingStreamID)
|
||||||
// header: [StreamID 4 bytes][Seq 4 bytes][ClosingStreamID 4 bytes]
|
// header: [StreamID 4 bytes][Seq 4 bytes][ClosingStreamID 4 bytes]
|
||||||
plainheader := make([]byte, 16)
|
iv := CryptoRandBytes(16)
|
||||||
copy(plainheader[0:12], header)
|
cipherheader := encrypt(iv, key, header)
|
||||||
copy(plainheader[12:], []byte{0x00, 0x00, 0x00, 0x00})
|
obfsed := make([]byte, len(f.Payload)+12+16)
|
||||||
// plainheader: [header 12 bytes][0x00,0x00,0x00,0x00]
|
|
||||||
iv := f.Payload[0:16]
|
|
||||||
cipherheader := encrypt(iv, key, plainheader)
|
|
||||||
obfsed := make([]byte, len(f.Payload)+12+4)
|
|
||||||
copy(obfsed[0:16], iv)
|
copy(obfsed[0:16], iv)
|
||||||
copy(obfsed[16:32], cipherheader)
|
copy(obfsed[16:28], cipherheader)
|
||||||
copy(obfsed[32:], f.Payload[16:])
|
copy(obfsed[28:], f.Payload)
|
||||||
// obfsed: [iv 16 bytes][cipherheader 16 bytes][payload w/o iv]
|
// obfsed: [iv 16 bytes][cipherheader 12 bytes][payload]
|
||||||
ret := AddRecordLayer(obfsed, []byte{0x17}, []byte{0x03, 0x03})
|
ret := AddRecordLayer(obfsed, []byte{0x17}, []byte{0x03, 0x03})
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
@ -53,14 +48,13 @@ func MakeObfs(key []byte) func(*mux.Frame) []byte {
|
||||||
func MakeDeobfs(key []byte) func([]byte) *mux.Frame {
|
func MakeDeobfs(key []byte) func([]byte) *mux.Frame {
|
||||||
deobfs := func(in []byte) *mux.Frame {
|
deobfs := func(in []byte) *mux.Frame {
|
||||||
peeled := PeelRecordLayer(in)
|
peeled := PeelRecordLayer(in)
|
||||||
plainheader := decrypt(peeled[0:16], key, peeled[16:32])
|
header := decrypt(peeled[0:16], key, peeled[16:28])
|
||||||
// plainheader: [header 12 bytes][0x00,0x00,0x00,0x00]
|
streamID := binary.BigEndian.Uint32(header[0:4])
|
||||||
streamID := binary.BigEndian.Uint32(plainheader[0:4])
|
seq := binary.BigEndian.Uint32(header[4:8])
|
||||||
seq := binary.BigEndian.Uint32(plainheader[4:8])
|
closingStreamID := binary.BigEndian.Uint32(header[8:12])
|
||||||
closingStreamID := binary.BigEndian.Uint32(plainheader[8:12])
|
payload := make([]byte, len(peeled)-12-16)
|
||||||
payload := make([]byte, len(peeled)-12-4)
|
//log.Printf("Payload: %x\n", payload)
|
||||||
copy(payload[0:16], peeled[0:16])
|
copy(payload, peeled[28:])
|
||||||
copy(payload[16:], peeled[32:])
|
|
||||||
ret := &mux.Frame{
|
ret := &mux.Frame{
|
||||||
StreamID: streamID,
|
StreamID: streamID,
|
||||||
Seq: seq,
|
Seq: seq,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue