Improve logging

This commit is contained in:
Qian Wang 2019-08-02 15:45:33 +01:00
parent c2c7c54761
commit 33f232475d
14 changed files with 119 additions and 91 deletions

View File

@ -8,7 +8,6 @@ import (
"flag" "flag"
"fmt" "fmt"
"io" "io"
"log"
"math/rand" "math/rand"
"net" "net"
"os" "os"
@ -20,6 +19,7 @@ import (
"github.com/cbeuw/Cloak/internal/client/TLS" "github.com/cbeuw/Cloak/internal/client/TLS"
mux "github.com/cbeuw/Cloak/internal/multiplex" mux "github.com/cbeuw/Cloak/internal/multiplex"
"github.com/cbeuw/Cloak/internal/util" "github.com/cbeuw/Cloak/internal/util"
log "github.com/sirupsen/logrus"
) )
var version string var version string
@ -51,7 +51,7 @@ func makeRemoteConn(sta *client.State) (net.Conn, []byte, error) {
// For android // For android
d := net.Dialer{Control: protector} d := net.Dialer{Control: protector}
clientHello, sharedSecret := TLS.ComposeInitHandshake(sta) clientHello, sharedSecret := TLS.ComposeClientHello(sta)
connectingIP := sta.RemoteHost connectingIP := sta.RemoteHost
if net.ParseIP(connectingIP).To4() == nil { if net.ParseIP(connectingIP).To4() == nil {
// IPv6 needs square brackets // IPv6 needs square brackets
@ -59,25 +59,25 @@ func makeRemoteConn(sta *client.State) (net.Conn, []byte, error) {
} }
remoteConn, err := d.Dial("tcp", connectingIP+":"+sta.RemotePort) remoteConn, err := d.Dial("tcp", connectingIP+":"+sta.RemotePort)
if err != nil { if err != nil {
log.Printf("Connecting to remote: %v\n", err) log.WithField("error", err).Error("Failed to connect to remote")
return nil, nil, err return nil, nil, err
} }
_, err = remoteConn.Write(clientHello) _, err = remoteConn.Write(clientHello)
if err != nil { if err != nil {
log.Printf("Sending ClientHello: %v\n", err) log.WithField("error", err).Error("Failed to send ClientHello")
return nil, nil, err return nil, nil, err
} }
buf := make([]byte, 1024) buf := make([]byte, 1024)
_, err = util.ReadTLS(remoteConn, buf) _, err = util.ReadTLS(remoteConn, buf)
if err != nil { if err != nil {
log.Printf("Reading ServerHello: %v\n", err) log.WithField("error", err).Error("Failed to read ServerHello")
} }
serverRandom := buf[11:43] serverRandom := buf[11:43]
sessionKey := client.DecryptSessionKey(serverRandom, sharedSecret) sessionKey := client.DecryptSessionKey(serverRandom, sharedSecret)
_, err = util.ReadTLS(remoteConn, buf) _, err = util.ReadTLS(remoteConn, buf)
if err != nil { if err != nil {
log.Printf("Reading Change Cipher Spec %v\n", err) log.WithField("error", err).Error("Failed to read ChangeCipherSpec")
return nil, nil, err return nil, nil, err
} }
@ -86,7 +86,7 @@ func makeRemoteConn(sta *client.State) (net.Conn, []byte, error) {
} }
func makeSession(sta *client.State) *mux.Session { func makeSession(sta *client.State) *mux.Session {
log.Println("Attemtping to start a new session") log.Info("Attemtping to start a new session")
if !sta.IsAdmin { if !sta.IsAdmin {
// sessionID is usergenerated. There shouldn't be a security concern because the scope of // sessionID is usergenerated. There shouldn't be a security concern because the scope of
// sessionID is limited to its UID. // sessionID is limited to its UID.
@ -105,7 +105,8 @@ func makeSession(sta *client.State) *mux.Session {
conn, sk, err := makeRemoteConn(sta) conn, sk, err := makeRemoteConn(sta)
_sessionKey.Store(sk) _sessionKey.Store(sk)
if err != nil { if err != nil {
log.Printf("Failed to establish new connections to remote: %v\n", err) log.Errorf("Failed to establish new connections to remote: %v", err)
// TODO increase the interval if failed multiple times
time.Sleep(time.Second * 3) time.Sleep(time.Second * 3)
goto makeconn goto makeconn
} }
@ -127,7 +128,7 @@ func makeSession(sta *client.State) *mux.Session {
sesh.AddConnection(conn) sesh.AddConnection(conn)
} }
log.Printf("Session %v established", sta.SessionID) log.Infof("Session %v established", sta.SessionID)
return sesh return sesh
} }
@ -143,9 +144,8 @@ func main() {
var config string var config string
var b64AdminUID string var b64AdminUID string
log.SetFlags(log.LstdFlags | log.Lshortfile)
log_init() log_init()
log.SetLevel(log.DebugLevel)
if os.Getenv("SS_LOCAL_HOST") != "" { if os.Getenv("SS_LOCAL_HOST") != "" {
localHost = os.Getenv("SS_LOCAL_HOST") localHost = os.Getenv("SS_LOCAL_HOST")
@ -165,7 +165,7 @@ func main() {
flag.Parse() flag.Parse()
if *askVersion { if *askVersion {
fmt.Printf("ck-client %s\n", version) fmt.Printf("ck-client %s", version)
return return
} }
@ -174,7 +174,7 @@ func main() {
return return
} }
log.Println("Starting standalone mode") log.Info("Starting standalone mode")
} }
sta := client.InitState(localHost, localPort, remoteHost, remotePort, time.Now) sta := client.InitState(localHost, localPort, remoteHost, remotePort, time.Now)
@ -200,7 +200,6 @@ func main() {
listeningIP = "[" + listeningIP + "]" listeningIP = "[" + listeningIP + "]"
} }
listener, err := net.Listen("tcp", listeningIP+":"+sta.LocalPort) listener, err := net.Listen("tcp", listeningIP+":"+sta.LocalPort)
log.Println("Listening on " + listeningIP + ":" + sta.LocalPort)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -214,10 +213,13 @@ func main() {
} }
if adminUID != nil { if adminUID != nil {
log.Infof("API base is %v:%v", listeningIP, sta.LocalPort)
sta.IsAdmin = true sta.IsAdmin = true
sta.SessionID = 0 sta.SessionID = 0
sta.UID = adminUID sta.UID = adminUID
sta.NumConn = 1 sta.NumConn = 1
} else {
log.Infof("Listening on %v:%v for proxy clients", listeningIP, sta.LocalPort)
} }
var sesh *mux.Session var sesh *mux.Session
@ -225,7 +227,7 @@ func main() {
for { for {
localConn, err := listener.Accept() localConn, err := listener.Accept()
if err != nil { if err != nil {
log.Println(err) log.Error(err)
continue continue
} }
if sesh == nil || sesh.IsClosed() { if sesh == nil || sesh.IsClosed() {
@ -235,19 +237,19 @@ func main() {
data := make([]byte, 10240) data := make([]byte, 10240)
i, err := io.ReadAtLeast(localConn, data, 1) i, err := io.ReadAtLeast(localConn, data, 1)
if err != nil { if err != nil {
log.Println(err) log.Errorf("Failed to read first packet from proxy client: %v", err)
localConn.Close() localConn.Close()
return return
} }
stream, err := sesh.OpenStream() stream, err := sesh.OpenStream()
if err != nil { if err != nil {
log.Println(err) log.Errorf("Failed to open stream: %v", err)
localConn.Close() localConn.Close()
return return
} }
_, err = stream.Write(data[:i]) _, err = stream.Write(data[:i])
if err != nil { if err != nil {
log.Println(err) log.Errorf("Failed to write to stream: %v", err)
localConn.Close() localConn.Close()
stream.Close() stream.Close()
return return

View File

@ -28,7 +28,7 @@ import "C"
import ( import (
"bufio" "bufio"
"log" log "github.com/sirupsen/logrus"
"os" "os"
"unsafe" "unsafe"
) )
@ -66,8 +66,6 @@ func lineLog(f *os.File, priority C.int) {
func log_init() { func log_init() {
log.SetOutput(infoWriter{}) log.SetOutput(infoWriter{})
// android logcat includes all of log.LstdFlags
log.SetFlags(log.Flags() &^ log.LstdFlags)
r, w, err := os.Pipe() r, w, err := os.Pipe()
if err != nil { if err != nil {

View File

@ -67,7 +67,7 @@ package main
import "C" import "C"
import ( import (
"log" log "github.com/sirupsen/logrus"
"syscall" "syscall"
) )

View File

@ -7,7 +7,6 @@ import (
"flag" "flag"
"fmt" "fmt"
"io" "io"
"log"
"net" "net"
"net/http" "net/http"
_ "net/http/pprof" _ "net/http/pprof"
@ -19,9 +18,10 @@ import (
mux "github.com/cbeuw/Cloak/internal/multiplex" mux "github.com/cbeuw/Cloak/internal/multiplex"
"github.com/cbeuw/Cloak/internal/server" "github.com/cbeuw/Cloak/internal/server"
"github.com/cbeuw/Cloak/internal/util" "github.com/cbeuw/Cloak/internal/util"
log "github.com/sirupsen/logrus"
) )
var b64 = base64.StdEncoding var b64 = base64.StdEncoding.EncodeToString
var version string var version string
func pipe(dst io.ReadWriteCloser, src io.ReadWriteCloser) { func pipe(dst io.ReadWriteCloser, src io.ReadWriteCloser) {
@ -46,6 +46,12 @@ func pipe(dst io.ReadWriteCloser, src io.ReadWriteCloser) {
} }
func dispatchConnection(conn net.Conn, sta *server.State) { func dispatchConnection(conn net.Conn, sta *server.State) {
remoteAddr := conn.RemoteAddr()
var err error
rejectLogger := log.WithFields(log.Fields{
"remoteAddr": remoteAddr,
"error": err,
})
buf := make([]byte, 1500) buf := make([]byte, 1500)
conn.SetReadDeadline(time.Now().Add(3 * time.Second)) conn.SetReadDeadline(time.Now().Add(3 * time.Second))
@ -60,7 +66,7 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
goWeb := func() { goWeb := func() {
webConn, err := net.Dial("tcp", sta.RedirAddr) webConn, err := net.Dial("tcp", sta.RedirAddr)
if err != nil { if err != nil {
log.Printf("Making connection to redirection server: %v\n", err) log.Errorf("Making connection to redirection server: %v", err)
return return
} }
webConn.Write(data) webConn.Write(data)
@ -70,26 +76,33 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
ch, err := server.ParseClientHello(data) ch, err := server.ParseClientHello(data)
if err != nil { if err != nil {
log.Printf("+1 non Cloak non (or malformed) TLS traffic from %v\n", conn.RemoteAddr()) rejectLogger.Warn("+1 non Cloak non (or malformed) TLS traffic")
goWeb() goWeb()
return return
} }
isCloak, UID, sessionID, proxyMethod, encryptionMethod, sharedSecret := server.TouchStone(ch, sta) UID, sessionID, proxyMethod, encryptionMethod, sharedSecret, err := server.TouchStone(ch, sta)
if !isCloak { if err != nil {
log.Printf("+1 non Cloak TLS traffic from %v\n", conn.RemoteAddr()) rejectLogger.Warn("+1 non Cloak TLS traffic")
goWeb() goWeb()
return return
} }
if _, ok := sta.ProxyBook[proxyMethod]; !ok { if _, ok := sta.ProxyBook[proxyMethod]; !ok {
log.Printf("+1 Cloak TLS traffic with invalid proxy method `%v` from %v\n", proxyMethod, conn.RemoteAddr()) log.WithFields(log.Fields{
"UID": UID,
"proxyMethod": proxyMethod,
}).Warn("+1 Cloak TLS traffic with invalid proxy method")
goWeb() goWeb()
return return
} }
user, err := sta.Panel.GetUser(UID) user, err := sta.Panel.GetUser(UID)
if err != nil { if err != nil {
log.Printf("+1 unauthorised user from %v, uid: %v\n", conn.RemoteAddr(), base64.StdEncoding.EncodeToString(UID)) log.WithFields(log.Fields{
"UID": b64(UID),
"remoteAddr": remoteAddr,
"error": err,
}).Warn("+1 unauthorised UID")
goWeb() goWeb()
return return
} }
@ -108,21 +121,21 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
rand.Read(sessionKey) rand.Read(sessionKey)
obfs, deobfs, err := util.GenerateObfs(encryptionMethod, sessionKey) obfs, deobfs, err := util.GenerateObfs(encryptionMethod, sessionKey)
if err != nil { if err != nil {
log.Println(err) log.Error(err)
goWeb() goWeb()
} }
sesh, existing, err := user.GetSession(sessionID, obfs, deobfs, sessionKey, util.ReadTLS) sesh, existing, err := user.GetSession(sessionID, obfs, deobfs, sessionKey, util.ReadTLS)
if err != nil { if err != nil {
user.DelSession(sessionID) user.DelSession(sessionID)
log.Println(err) log.Error(err)
return return
} }
if existing { if existing {
err = finishHandshake(sesh.SessionKey) err = finishHandshake(sesh.SessionKey)
if err != nil { if err != nil {
log.Println(err) log.Error(err)
return return
} }
sesh.AddConnection(conn) sesh.AddConnection(conn)
@ -135,7 +148,7 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
if bytes.Equal(UID, sta.AdminUID) && sessionID == 0 { if bytes.Equal(UID, sta.AdminUID) && sessionID == 0 {
err = finishHandshake(sessionKey) err = finishHandshake(sessionKey)
if err != nil { if err != nil {
log.Println(err) log.Error(err)
return return
} }
sesh := mux.MakeSession(0, mux.UNLIMITED_VALVE, obfs, deobfs, sessionKey, util.ReadTLS) sesh := mux.MakeSession(0, mux.UNLIMITED_VALVE, obfs, deobfs, sessionKey, util.ReadTLS)
@ -143,25 +156,32 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
//TODO: Router could be nil in cnc mode //TODO: Router could be nil in cnc mode
err = http.Serve(sesh, sta.LocalAPIRouter) err = http.Serve(sesh, sta.LocalAPIRouter)
if err != nil { if err != nil {
log.Println(err) log.Error(err)
return return
} }
} }
err = finishHandshake(sessionKey) err = finishHandshake(sessionKey)
if err != nil { if err != nil {
log.Println(err) log.Error(err)
return return
} }
log.Printf("New session from UID:%v, sessionID:%v\n", b64.EncodeToString(UID), sessionID) log.WithFields(log.Fields{
"UID": b64(UID),
"sessionID": sessionID,
}).Info("New session")
sesh.AddConnection(conn) sesh.AddConnection(conn)
for { for {
newStream, err := sesh.Accept() newStream, err := sesh.Accept()
if err != nil { if err != nil {
if err == mux.ErrBrokenSession { if err == mux.ErrBrokenSession {
log.Printf("Session closed for UID:%v, sessionID:%v, reason:%v\n", b64.EncodeToString(UID), sessionID, sesh.TerminalMsg()) log.WithFields(log.Fields{
"UID": b64(UID),
"sessionID": sessionID,
"reason": sesh.TerminalMsg(),
}).Info("Session closed")
user.DelSession(sessionID) user.DelSession(sessionID)
return return
} else { } else {
@ -170,7 +190,7 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
} }
localConn, err := net.Dial("tcp", sta.ProxyBook[proxyMethod]) localConn, err := net.Dial("tcp", sta.ProxyBook[proxyMethod])
if err != nil { if err != nil {
log.Printf("Failed to connect to %v: %v\n", proxyMethod, err) log.Errorf("Failed to connect to %v: %v", proxyMethod, err)
continue continue
} }
go pipe(localConn, newStream) go pipe(localConn, newStream)
@ -186,7 +206,7 @@ func main() {
var bindPort string var bindPort string
var config string var config string
log.SetFlags(log.LstdFlags | log.Lshortfile) log.SetLevel(log.DebugLevel)
if os.Getenv("SS_LOCAL_HOST") != "" { if os.Getenv("SS_LOCAL_HOST") != "" {
bindHost = os.Getenv("SS_REMOTE_HOST") bindHost = os.Getenv("SS_REMOTE_HOST")
@ -207,7 +227,7 @@ func main() {
flag.Parse() flag.Parse()
if *askVersion { if *askVersion {
fmt.Printf("ck-server %s\n", version) fmt.Printf("ck-server %s", version)
return return
} }
if *printUsage { if *printUsage {
@ -227,13 +247,13 @@ func main() {
if *pprofAddr != "" { if *pprofAddr != "" {
runtime.SetBlockProfileRate(5) runtime.SetBlockProfileRate(5)
go func() { go func() {
log.Println(http.ListenAndServe(*pprofAddr, nil)) log.Info(http.ListenAndServe(*pprofAddr, nil))
}() }()
log.Println("pprof listening on " + *pprofAddr) log.Infof("pprof listening on %v", *pprofAddr)
} }
log.Printf("Starting standalone mode, listening on %v:%v", bindHost, bindPort) log.Infof("Starting standalone mode, listening on %v:%v", bindHost, bindPort)
} }
sta, _ := server.InitState(bindHost, bindPort, time.Now) sta, _ := server.InitState(bindHost, bindPort, time.Now)
@ -254,14 +274,14 @@ func main() {
listen := func(addr, port string) { listen := func(addr, port string) {
listener, err := net.Listen("tcp", addr+":"+port) listener, err := net.Listen("tcp", addr+":"+port)
log.Println("Listening on " + addr + ":" + port) log.Infof("Listening on " + addr + ":" + port)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
for { for {
conn, err := listener.Accept() conn, err := listener.Accept()
if err != nil { if err != nil {
log.Printf("%v", err) log.Errorf("%v", err)
continue continue
} }
go dispatchConnection(conn, sta) go dispatchConnection(conn, sta)

View File

@ -8,12 +8,12 @@ import (
func generateUID() string { func generateUID() string {
UID := make([]byte, 16) UID := make([]byte, 16)
rand.Read(UID) rand.Read(UID)
return b64.EncodeToString(UID) return b64(UID)
} }
func generateKeyPair() (string, string) { func generateKeyPair() (string, string) {
staticPv, staticPub, _ := ecdh.GenerateKey(rand.Reader) staticPv, staticPub, _ := ecdh.GenerateKey(rand.Reader)
marshPub := ecdh.Marshal(staticPub) marshPub := ecdh.Marshal(staticPub)
marshPv := staticPv.(*[32]byte)[:] marshPv := staticPv.(*[32]byte)[:]
return b64.EncodeToString(marshPub), b64.EncodeToString(marshPv) return b64(marshPub), b64(marshPv)
} }

2
go.mod
View File

@ -5,7 +5,7 @@ require (
github.com/gorilla/mux v1.7.3 github.com/gorilla/mux v1.7.3
github.com/juju/ratelimit v1.0.1 github.com/juju/ratelimit v1.0.1
github.com/kr/pretty v0.1.0 // indirect github.com/kr/pretty v0.1.0 // indirect
github.com/sirupsen/logrus v1.4.2
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
) )

15
go.sum
View File

@ -1,17 +1,28 @@
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/juju/ratelimit v1.0.1 h1:+7AIFJVQ0EQgq/K9+0Krm7m530Du7tIz0METWzN0RgY= github.com/juju/ratelimit v1.0.1 h1:+7AIFJVQ0EQgq/K9+0Krm7m530Du7tIz0METWzN0RgY=
github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b h1:Elez2XeF2p9uyVj0yEUDqQ56NFcDtcBNkYP7yv8YbUE= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b h1:Elez2XeF2p9uyVj0yEUDqQ56NFcDtcBNkYP7yv8YbUE=
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e h1:3GIlrlVLfkoipSReOMNAgApI0ajnalyLa/EZHHca/XI= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@ -2,7 +2,6 @@ package multiplex
import ( import (
"errors" "errors"
//"log"
"net" "net"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -122,7 +121,6 @@ func (sesh *Session) getStream(id uint32, closingFrame bool) *Stream {
stream = makeStream(id, sesh) stream = makeStream(id, sesh)
sesh.streams[id] = stream sesh.streams[id] = stream
sesh.acceptCh <- stream sesh.acceptCh <- stream
//log.Printf("Adding stream %v\n", id)
return stream return stream
} }
} }

View File

@ -5,7 +5,7 @@ import (
"net" "net"
"time" "time"
//"log" log "github.com/sirupsen/logrus"
"math" "math"
prand "math/rand" prand "math/rand"
"sync" "sync"
@ -48,6 +48,7 @@ func makeStream(id uint32, sesh *Session) *Stream {
sortedBuf: NewBufferedPipe(), sortedBuf: NewBufferedPipe(),
} }
go stream.recvNewFrame() go stream.recvNewFrame()
log.Tracef("stream %v opened", id)
return stream return stream
} }
@ -112,7 +113,7 @@ func (s *Stream) _close() {
func (s *Stream) passiveClose() { func (s *Stream) passiveClose() {
s._close() s._close()
s.session.delStream(s.id) s.session.delStream(s.id)
//log.Printf("%v passive closing\n", stream.id) log.WithField("streamId", s.id).Trace("stream passively closed")
} }
// active close. Close locally and tell the remote that this stream is being closed // active close. Close locally and tell the remote that this stream is being closed
@ -140,7 +141,7 @@ func (s *Stream) Close() error {
s._close() s._close()
s.session.delStream(s.id) s.session.delStream(s.id)
//log.Printf("%v actively closed\n", stream.id) log.WithField("streamId", s.id).Trace("stream actively closed")
return nil return nil
} }
@ -149,6 +150,7 @@ func (s *Stream) Close() error {
// We don't notify the remote because session.Close() is always // We don't notify the remote because session.Close() is always
// called when the session is passively closed // called when the session is passively closed
func (s *Stream) closeNoDelMap() { func (s *Stream) closeNoDelMap() {
log.WithField("streamId", s.id).Trace("stream closed by session")
s._close() s._close()
} }

View File

@ -2,7 +2,7 @@ package multiplex
import ( import (
"errors" "errors"
"log" log "github.com/sirupsen/logrus"
"net" "net"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -129,7 +129,7 @@ func (sb *switchboard) deplex(ce *connEnclave) {
sb.rxWait(n) sb.rxWait(n)
sb.Valve.AddRx(int64(n)) sb.Valve.AddRx(int64(n))
if err != nil { if err != nil {
//log.Println(err) log.Tracef("a connection for session %v has closed: %v", sb.session.id, err)
go ce.remoteConn.Close() go ce.remoteConn.Close()
sb.removeConn(ce) sb.removeConn(ce)
return return
@ -137,7 +137,7 @@ func (sb *switchboard) deplex(ce *connEnclave) {
frame, err := sb.session.deobfs(buf[:n]) frame, err := sb.session.deobfs(buf[:n])
if err != nil { if err != nil {
log.Println(err) log.Debugf("Failed to decrypt a frame for session %v: %v", sb.session.id, err)
continue continue
} }

View File

@ -3,12 +3,18 @@ package server
import ( import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"errors"
"fmt"
"github.com/cbeuw/Cloak/internal/ecdh" "github.com/cbeuw/Cloak/internal/ecdh"
"github.com/cbeuw/Cloak/internal/util" "github.com/cbeuw/Cloak/internal/util"
"log"
) )
func TouchStone(ch *ClientHello, sta *State) (isCK bool, UID []byte, sessionID uint32, proxyMethod string, encryptionMethod byte, sharedSecret []byte) { var ErrReplay = errors.New("duplicate random")
var ErrInvalidPubKey = errors.New("public key has invalid format")
var ErrCiphertextLength = errors.New("ciphertext has the wrong length")
var ErrTimestampOutOfWindow = errors.New("timestamp is outside of the accepting window")
func TouchStone(ch *ClientHello, sta *State) (UID []byte, sessionID uint32, proxyMethod string, encryptionMethod byte, sharedSecret []byte, err error) {
var random [32]byte var random [32]byte
copy(random[:], ch.random) copy(random[:], ch.random)
@ -18,27 +24,31 @@ func TouchStone(ch *ClientHello, sta *State) (isCK bool, UID []byte, sessionID u
sta.usedRandomM.Unlock() sta.usedRandomM.Unlock()
if used != 0 { if used != 0 {
log.Println("Replay! Duplicate random") err = ErrReplay
return return
} }
ephPub, ok := ecdh.Unmarshal(random[:]) ephPub, ok := ecdh.Unmarshal(random[:])
if !ok { if !ok {
err = ErrInvalidPubKey
return return
} }
sharedSecret = ecdh.GenerateSharedSecret(sta.staticPv, ephPub) sharedSecret = ecdh.GenerateSharedSecret(sta.staticPv, ephPub)
keyShare, err := parseKeyShare(ch.extensions[[2]byte{0x00, 0x33}]) var keyShare []byte
keyShare, err = parseKeyShare(ch.extensions[[2]byte{0x00, 0x33}])
if err != nil { if err != nil {
return return
} }
ciphertext := append(ch.sessionId, keyShare...)
ciphertext := append(ch.sessionId, keyShare...)
if len(ciphertext) != 64 { if len(ciphertext) != 64 {
err = fmt.Errorf("%v: %v", ErrCiphertextLength, len(ciphertext))
return return
} }
plaintext, err := util.AESGCMDecrypt(random[0:12], sharedSecret, ciphertext) var plaintext []byte
plaintext, err = util.AESGCMDecrypt(random[0:12], sharedSecret, ciphertext)
if err != nil { if err != nil {
return return
} }
@ -48,11 +58,9 @@ func TouchStone(ch *ClientHello, sta *State) (isCK bool, UID []byte, sessionID u
encryptionMethod = plaintext[28] encryptionMethod = plaintext[28]
timestamp := int64(binary.BigEndian.Uint64(plaintext[29:37])) timestamp := int64(binary.BigEndian.Uint64(plaintext[29:37]))
if timestamp/int64(TIMESTAMP_WINDOW.Seconds()) != sta.Now().Unix()/int64(TIMESTAMP_WINDOW.Seconds()) { if timestamp/int64(TIMESTAMP_WINDOW.Seconds()) != sta.Now().Unix()/int64(TIMESTAMP_WINDOW.Seconds()) {
isCK = false err = fmt.Errorf("%v: received timestamp %v", ErrTimestampOutOfWindow, timestamp)
return return
} }
sessionID = binary.BigEndian.Uint32(plaintext[37:41]) sessionID = binary.BigEndian.Uint32(plaintext[37:41])
isCK = true
return return
} }

View File

@ -2,7 +2,7 @@ package server
import ( import (
"encoding/binary" "encoding/binary"
"log" log "github.com/sirupsen/logrus"
"net/http" "net/http"
"time" "time"
@ -157,7 +157,7 @@ func (manager *localManager) uploadStatus(uploads []statusUpdate) ([]statusRespo
} }
err := bucket.Put([]byte("UpCredit"), i64ToB(newUp)) err := bucket.Put([]byte("UpCredit"), i64ToB(newUp))
if err != nil { if err != nil {
log.Println(err) log.Error(err)
continue continue
} }
@ -174,7 +174,7 @@ func (manager *localManager) uploadStatus(uploads []statusUpdate) ([]statusRespo
} }
err = bucket.Put([]byte("DownCredit"), i64ToB(newDown)) err = bucket.Put([]byte("DownCredit"), i64ToB(newDown))
if err != nil { if err != nil {
log.Println(err) log.Error(err)
continue continue
} }

View File

@ -1,12 +1,12 @@
package server package server
import ( import (
"log"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
mux "github.com/cbeuw/Cloak/internal/multiplex" mux "github.com/cbeuw/Cloak/internal/multiplex"
log "github.com/sirupsen/logrus"
) )
type userPanel struct { type userPanel struct {
@ -101,7 +101,7 @@ func (panel *userPanel) updateUsageQueueForOne(user *ActiveUser) {
} }
func (panel *userPanel) commitUpdate() { func (panel *userPanel) commitUpdate() error {
panel.usageUpdateQueueM.Lock() panel.usageUpdateQueueM.Lock()
statuses := make([]statusUpdate, 0, len(panel.usageUpdateQueue)) statuses := make([]statusUpdate, 0, len(panel.usageUpdateQueue))
for arrUID, usage := range panel.usageUpdateQueue { for arrUID, usage := range panel.usageUpdateQueue {
@ -125,7 +125,7 @@ func (panel *userPanel) commitUpdate() {
responses, err := panel.Manager.uploadStatus(statuses) responses, err := panel.Manager.uploadStatus(statuses)
if err != nil { if err != nil {
log.Println(err) return err
} }
for _, resp := range responses { for _, resp := range responses {
var arrUID [16]byte var arrUID [16]byte
@ -142,6 +142,7 @@ func (panel *userPanel) commitUpdate() {
} }
panel.usageUpdateQueue = make(map[[16]byte]*usagePair) panel.usageUpdateQueue = make(map[[16]byte]*usagePair)
panel.usageUpdateQueueM.Unlock() panel.usageUpdateQueueM.Unlock()
return nil
} }
func (panel *userPanel) regularQueueUpload() { func (panel *userPanel) regularQueueUpload() {
@ -149,7 +150,10 @@ func (panel *userPanel) regularQueueUpload() {
time.Sleep(1 * time.Minute) time.Sleep(1 * time.Minute)
go func() { go func() {
panel.updateUsageQueue() panel.updateUsageQueue()
panel.commitUpdate() err := panel.commitUpdate()
if err != nil {
log.Error(err)
}
}() }()
} }
} }

View File

@ -8,7 +8,6 @@ import (
mux "github.com/cbeuw/Cloak/internal/multiplex" mux "github.com/cbeuw/Cloak/internal/multiplex"
"golang.org/x/crypto/chacha20poly1305" "golang.org/x/crypto/chacha20poly1305"
"io" "io"
prand "math/rand"
"net" "net"
"strconv" "strconv"
) )
@ -41,14 +40,6 @@ func AESGCMDecrypt(nonce []byte, key []byte, ciphertext []byte) ([]byte, error)
return plain, nil return plain, nil
} }
// PsudoRandBytes returns a byte slice filled with psudorandom bytes generated by the seed
func PsudoRandBytes(length int, seed int64) []byte {
r := prand.New(prand.NewSource(seed))
ret := make([]byte, length)
r.Read(ret)
return ret
}
// ReadTLS reads TLS data according to its record layer // ReadTLS reads TLS data according to its record layer
func ReadTLS(conn net.Conn, buffer []byte) (n int, err error) { func ReadTLS(conn net.Conn, buffer []byte) (n int, err error) {
// TCP is a stream. Multiple TLS messages can arrive at the same time, // TCP is a stream. Multiple TLS messages can arrive at the same time,
@ -130,9 +121,3 @@ func AddRecordLayer(input []byte, typ []byte, ver []byte) []byte {
copy(ret[5:], input) copy(ret[5:], input)
return ret return ret
} }
// PeelRecordLayer peels off the record layer
func PeelRecordLayer(data []byte) []byte {
ret := data[5:]
return ret
}