mirror of https://github.com/cbeuw/Cloak
Client using AdminUID can now use the proxy without adding themselves to the db
This commit is contained in:
parent
ed1253ff4c
commit
36a743c3ca
|
|
@ -75,7 +75,7 @@ func adminHandshake(sta *client.State) (*administrator, error) {
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *administrator) getCommand() []byte {
|
func (a *administrator) getRequest() (req []byte, err error) {
|
||||||
fmt.Println("Select your command")
|
fmt.Println("Select your command")
|
||||||
fmt.Println(`1 listActiveUsers none []uids
|
fmt.Println(`1 listActiveUsers none []uids
|
||||||
2 listAllUsers none []userinfo
|
2 listAllUsers none []userinfo
|
||||||
|
|
@ -85,15 +85,18 @@ func (a *administrator) getCommand() []byte {
|
||||||
fmt.Scanln(&cmd)
|
fmt.Scanln(&cmd)
|
||||||
switch cmd {
|
switch cmd {
|
||||||
case "1":
|
case "1":
|
||||||
return a.request([]byte{0x01})
|
req = a.request([]byte{0x01})
|
||||||
|
return
|
||||||
case "2":
|
case "2":
|
||||||
return a.request([]byte{0x02})
|
req = a.request([]byte{0x02})
|
||||||
|
return
|
||||||
case "3":
|
case "3":
|
||||||
fmt.Println("Enter UID")
|
fmt.Println("Enter UID")
|
||||||
var b64UID string
|
var b64UID string
|
||||||
fmt.Scanln(&b64UID)
|
fmt.Scanln(&b64UID)
|
||||||
UID, _ := base64.StdEncoding.DecodeString(b64UID)
|
UID, _ := base64.StdEncoding.DecodeString(b64UID)
|
||||||
return a.request(append([]byte{0x03}, UID...))
|
req = a.request(append([]byte{0x03}, UID...))
|
||||||
|
return
|
||||||
case "4":
|
case "4":
|
||||||
var uinfo UserInfo
|
var uinfo UserInfo
|
||||||
var b64UID string
|
var b64UID string
|
||||||
|
|
@ -114,9 +117,10 @@ func (a *administrator) getCommand() []byte {
|
||||||
fmt.Printf("ExpiryTime:")
|
fmt.Printf("ExpiryTime:")
|
||||||
fmt.Scanf("%d", &uinfo.ExpiryTime)
|
fmt.Scanf("%d", &uinfo.ExpiryTime)
|
||||||
marshed, _ := json.Marshal(uinfo)
|
marshed, _ := json.Marshal(uinfo)
|
||||||
return a.request(append([]byte{0x04}, marshed...))
|
req = a.request(append([]byte{0x04}, marshed...))
|
||||||
|
return
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil, errors.New("Unreconised cmd")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,9 +86,14 @@ func adminPrompt(sta *client.State) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
log.Println(err)
|
||||||
buf := make([]byte, 16000)
|
buf := make([]byte, 16000)
|
||||||
for {
|
for {
|
||||||
req := a.getCommand()
|
req, err := a.getRequest()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
a.adminConn.Write(req)
|
a.adminConn.Write(req)
|
||||||
n, err := a.adminConn.Read(buf)
|
n, err := a.adminConn.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -112,7 +117,7 @@ func main() {
|
||||||
// The proxy port,should be 443
|
// The proxy port,should be 443
|
||||||
var remotePort string
|
var remotePort string
|
||||||
var pluginOpts string
|
var pluginOpts string
|
||||||
var isAdmin bool
|
var isAdmin *bool
|
||||||
|
|
||||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||||
|
|
||||||
|
|
@ -131,7 +136,7 @@ func main() {
|
||||||
flag.StringVar(&remotePort, "p", "443", "remotePort: proxy port, should be 443")
|
flag.StringVar(&remotePort, "p", "443", "remotePort: proxy port, should be 443")
|
||||||
flag.StringVar(&pluginOpts, "c", "ckclient.json", "pluginOpts: path to ckclient.json or options seperated with semicolons")
|
flag.StringVar(&pluginOpts, "c", "ckclient.json", "pluginOpts: path to ckclient.json or options seperated with semicolons")
|
||||||
askVersion := flag.Bool("v", false, "Print the version number")
|
askVersion := flag.Bool("v", false, "Print the version number")
|
||||||
isAdmin = *flag.Bool("a", false, "Admin mode")
|
isAdmin = flag.Bool("a", false, "Admin mode")
|
||||||
printUsage := flag.Bool("h", false, "Print this message")
|
printUsage := flag.Bool("h", false, "Print this message")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
|
@ -151,7 +156,12 @@ func main() {
|
||||||
// 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.
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
sessionID := rand.Uint32()
|
var sessionID uint32
|
||||||
|
if *isAdmin {
|
||||||
|
sessionID = 0
|
||||||
|
} else {
|
||||||
|
sessionID = rand.Uint32()
|
||||||
|
}
|
||||||
|
|
||||||
// opaque is used to generate the padding of session ticket
|
// opaque is used to generate the padding of session ticket
|
||||||
sta := client.InitState(localHost, localPort, remoteHost, remotePort, time.Now, sessionID)
|
sta := client.InitState(localHost, localPort, remoteHost, remotePort, time.Now, sessionID)
|
||||||
|
|
@ -160,7 +170,7 @@ func main() {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if isAdmin {
|
if *isAdmin {
|
||||||
err = adminPrompt(sta)
|
err = adminPrompt(sta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ 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/server/usermanager"
|
||||||
"github.com/cbeuw/Cloak/internal/util"
|
"github.com/cbeuw/Cloak/internal/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -78,13 +79,12 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if bytes.Equal(UID, sta.AdminUID) {
|
finishHandshake := func() error {
|
||||||
reply := server.ComposeReply(ch)
|
reply := server.ComposeReply(ch)
|
||||||
_, err = conn.Write(reply)
|
_, err = conn.Write(reply)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Sending reply to remote: %v\n", err)
|
|
||||||
go conn.Close()
|
go conn.Close()
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Two discarded messages: ChangeCipherSpec and Finished
|
// Two discarded messages: ChangeCipherSpec and Finished
|
||||||
|
|
@ -92,12 +92,19 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
|
||||||
for c := 0; c < 2; c++ {
|
for c := 0; c < 2; c++ {
|
||||||
_, err = util.ReadTLS(conn, discardBuf)
|
_, err = util.ReadTLS(conn, discardBuf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Reading discarded message %v: %v\n", c, err)
|
|
||||||
go conn.Close()
|
go conn.Close()
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if bytes.Equal(UID, sta.AdminUID) && sessionID == 0 {
|
||||||
|
err = finishHandshake()
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
c := sta.Userpanel.MakeController(sta.AdminUID)
|
c := sta.Userpanel.MakeController(sta.AdminUID)
|
||||||
for {
|
for {
|
||||||
n, err := conn.Read(data)
|
n, err := conn.Read(data)
|
||||||
|
|
@ -107,6 +114,7 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
|
||||||
}
|
}
|
||||||
resp, err := c.HandleRequest(data[:n])
|
resp, err := c.HandleRequest(data[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err = conn.Write(resp)
|
_, err = conn.Write(resp)
|
||||||
|
|
@ -117,33 +125,26 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
user, err := sta.Userpanel.GetAndActivateUser(UID)
|
|
||||||
|
var user *usermanager.User
|
||||||
|
if bytes.Equal(UID, sta.AdminUID) {
|
||||||
|
user, err = sta.Userpanel.GetAndActivateAdminUser(UID)
|
||||||
|
} else {
|
||||||
|
user, err = sta.Userpanel.GetAndActivateUser(UID)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("+1 unauthorised user from %v, uid: %x\n", conn.RemoteAddr(), UID)
|
log.Printf("+1 unauthorised user from %v, uid: %x\n", conn.RemoteAddr(), UID)
|
||||||
goWeb(data)
|
goWeb(data)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
reply := server.ComposeReply(ch)
|
err = finishHandshake()
|
||||||
_, err = conn.Write(reply)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Sending reply to remote: %v\n", err)
|
log.Println(err)
|
||||||
go conn.Close()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Two discarded messages: ChangeCipherSpec and Finished
|
if sesh, existing := user.GetSession(sessionID, mux.MakeObfs(UID), mux.MakeDeobfs(UID), util.ReadTLS); existing {
|
||||||
discardBuf := make([]byte, 1024)
|
|
||||||
for c := 0; c < 2; c++ {
|
|
||||||
_, err = util.ReadTLS(conn, discardBuf)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Reading discarded message %v: %v\n", c, err)
|
|
||||||
go conn.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if sesh, existing := user.GetOrCreateSession(sessionID, mux.MakeObfs(UID), mux.MakeDeobfs(UID), util.ReadTLS); existing {
|
|
||||||
sesh.AddConnection(conn)
|
sesh.AddConnection(conn)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ type Deobfser func([]byte) (*Frame, error)
|
||||||
|
|
||||||
// For each frame, the three parts of the header is xored with three keys.
|
// For each frame, the three parts of the header is xored with three keys.
|
||||||
// The keys are generated from the SID and the payload of the frame.
|
// The keys are generated from the SID and the payload of the frame.
|
||||||
// FIXME: this code will panic if len(data)<18.
|
|
||||||
func genXorKeys(secret []byte, data []byte) (i uint32, ii uint32, iii uint32) {
|
func genXorKeys(secret []byte, data []byte) (i uint32, ii uint32, iii uint32) {
|
||||||
h := xxhash.New32()
|
h := xxhash.New32()
|
||||||
ret := make([]uint32, 3)
|
ret := make([]uint32, 3)
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ var ErrBrokenSession = errors.New("broken session")
|
||||||
var errRepeatSessionClosing = errors.New("trying to close a closed session")
|
var errRepeatSessionClosing = errors.New("trying to close a closed session")
|
||||||
|
|
||||||
type Session struct {
|
type Session struct {
|
||||||
id uint32 // This field isn't acutally used
|
id uint32
|
||||||
|
|
||||||
// Used in Stream.Write. Add multiplexing headers, encrypt and add TLS header
|
// Used in Stream.Write. Add multiplexing headers, encrypt and add TLS header
|
||||||
obfs Obfser
|
obfs Obfser
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ type rawConfig struct {
|
||||||
WebServerAddr string
|
WebServerAddr string
|
||||||
PrivateKey string
|
PrivateKey string
|
||||||
AdminUID string
|
AdminUID string
|
||||||
|
SingleUser bool
|
||||||
}
|
}
|
||||||
type stateManager interface {
|
type stateManager interface {
|
||||||
ParseConfig(string) error
|
ParseConfig(string) error
|
||||||
|
|
|
||||||
|
|
@ -65,13 +65,6 @@ func (u *User) updateInfo(uinfo UserInfo) {
|
||||||
u.setExpiryTime(uinfo.ExpiryTime)
|
u.setExpiryTime(uinfo.ExpiryTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) GetSession(sessionID uint32) *mux.Session {
|
|
||||||
u.sessionsM.RLock()
|
|
||||||
sesh := u.sessions[sessionID]
|
|
||||||
u.sessionsM.RUnlock()
|
|
||||||
return sesh
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) PutSession(sessionID uint32, sesh *mux.Session) {
|
func (u *User) PutSession(sessionID uint32, sesh *mux.Session) {
|
||||||
u.sessionsM.Lock()
|
u.sessionsM.Lock()
|
||||||
u.sessions[sessionID] = sesh
|
u.sessions[sessionID] = sesh
|
||||||
|
|
@ -89,7 +82,7 @@ func (u *User) DelSession(sessionID uint32) {
|
||||||
u.sessionsM.Unlock()
|
u.sessionsM.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) GetOrCreateSession(sessionID uint32, obfs mux.Obfser, deobfs mux.Deobfser, obfsedRead func(net.Conn, []byte) (int, error)) (sesh *mux.Session, existing bool) {
|
func (u *User) GetSession(sessionID uint32, obfs mux.Obfser, deobfs mux.Deobfser, obfsedRead func(net.Conn, []byte) (int, error)) (sesh *mux.Session, existing bool) {
|
||||||
// TODO: session cap
|
// TODO: session cap
|
||||||
u.sessionsM.Lock()
|
u.sessionsM.Lock()
|
||||||
if sesh = u.sessions[sessionID]; sesh != nil {
|
if sesh = u.sessions[sessionID]; sesh != nil {
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,31 @@ func (up *Userpanel) backupDB(bakPath string) error {
|
||||||
var ErrUserNotFound = errors.New("User does not exist in db")
|
var ErrUserNotFound = errors.New("User does not exist in db")
|
||||||
var ErrUserNotActive = errors.New("User is not active")
|
var ErrUserNotActive = errors.New("User is not active")
|
||||||
|
|
||||||
|
func (up *Userpanel) GetAndActivateAdminUser(AdminUID []byte) (*User, error) {
|
||||||
|
up.activeUsersM.Lock()
|
||||||
|
var arrUID [32]byte
|
||||||
|
copy(arrUID[:], AdminUID)
|
||||||
|
if user, ok := up.activeUsers[arrUID]; ok {
|
||||||
|
up.activeUsersM.Unlock()
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
uinfo := UserInfo{
|
||||||
|
UID: AdminUID,
|
||||||
|
SessionsCap: 1e9,
|
||||||
|
UpRate: 1e12,
|
||||||
|
DownRate: 1e12,
|
||||||
|
UpCredit: 1e15,
|
||||||
|
DownCredit: 1e15,
|
||||||
|
ExpiryTime: 1e15,
|
||||||
|
}
|
||||||
|
|
||||||
|
user := MakeUser(up, &uinfo)
|
||||||
|
up.activeUsers[arrUID] = user
|
||||||
|
up.activeUsersM.Unlock()
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: expiry check
|
// TODO: expiry check
|
||||||
|
|
||||||
// GetUser is used to retrieve a user if s/he is active, or to retrieve the user's infor
|
// GetUser is used to retrieve a user if s/he is active, or to retrieve the user's infor
|
||||||
|
|
@ -253,7 +278,6 @@ func (up *Userpanel) addNewUser(uinfo UserInfo) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// FIXME: obnoxious code
|
|
||||||
if err = b.Put([]byte("SessionsCap"), u32ToB(uinfo.SessionsCap)); err != nil {
|
if err = b.Put([]byte("SessionsCap"), u32ToB(uinfo.SessionsCap)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue