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
|
||||
}
|
||||
|
||||
func (a *administrator) getCommand() []byte {
|
||||
func (a *administrator) getRequest() (req []byte, err error) {
|
||||
fmt.Println("Select your command")
|
||||
fmt.Println(`1 listActiveUsers none []uids
|
||||
2 listAllUsers none []userinfo
|
||||
|
|
@ -85,15 +85,18 @@ func (a *administrator) getCommand() []byte {
|
|||
fmt.Scanln(&cmd)
|
||||
switch cmd {
|
||||
case "1":
|
||||
return a.request([]byte{0x01})
|
||||
req = a.request([]byte{0x01})
|
||||
return
|
||||
case "2":
|
||||
return a.request([]byte{0x02})
|
||||
req = a.request([]byte{0x02})
|
||||
return
|
||||
case "3":
|
||||
fmt.Println("Enter UID")
|
||||
var b64UID string
|
||||
fmt.Scanln(&b64UID)
|
||||
UID, _ := base64.StdEncoding.DecodeString(b64UID)
|
||||
return a.request(append([]byte{0x03}, UID...))
|
||||
req = a.request(append([]byte{0x03}, UID...))
|
||||
return
|
||||
case "4":
|
||||
var uinfo UserInfo
|
||||
var b64UID string
|
||||
|
|
@ -114,9 +117,10 @@ func (a *administrator) getCommand() []byte {
|
|||
fmt.Printf("ExpiryTime:")
|
||||
fmt.Scanf("%d", &uinfo.ExpiryTime)
|
||||
marshed, _ := json.Marshal(uinfo)
|
||||
return a.request(append([]byte{0x04}, marshed...))
|
||||
req = a.request(append([]byte{0x04}, marshed...))
|
||||
return
|
||||
default:
|
||||
return nil
|
||||
return nil, errors.New("Unreconised cmd")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,9 +86,14 @@ func adminPrompt(sta *client.State) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Println(err)
|
||||
buf := make([]byte, 16000)
|
||||
for {
|
||||
req := a.getCommand()
|
||||
req, err := a.getRequest()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
a.adminConn.Write(req)
|
||||
n, err := a.adminConn.Read(buf)
|
||||
if err != nil {
|
||||
|
|
@ -112,7 +117,7 @@ func main() {
|
|||
// The proxy port,should be 443
|
||||
var remotePort string
|
||||
var pluginOpts string
|
||||
var isAdmin bool
|
||||
var isAdmin *bool
|
||||
|
||||
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(&pluginOpts, "c", "ckclient.json", "pluginOpts: path to ckclient.json or options seperated with semicolons")
|
||||
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")
|
||||
flag.Parse()
|
||||
|
||||
|
|
@ -151,7 +156,12 @@ func main() {
|
|||
// sessionID is usergenerated. There shouldn't be a security concern because the scope of
|
||||
// sessionID is limited to its UID.
|
||||
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
|
||||
sta := client.InitState(localHost, localPort, remoteHost, remotePort, time.Now, sessionID)
|
||||
|
|
@ -160,7 +170,7 @@ func main() {
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if isAdmin {
|
||||
if *isAdmin {
|
||||
err = adminPrompt(sta)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import (
|
|||
|
||||
mux "github.com/cbeuw/Cloak/internal/multiplex"
|
||||
"github.com/cbeuw/Cloak/internal/server"
|
||||
"github.com/cbeuw/Cloak/internal/server/usermanager"
|
||||
"github.com/cbeuw/Cloak/internal/util"
|
||||
)
|
||||
|
||||
|
|
@ -78,13 +79,12 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
|
|||
return
|
||||
}
|
||||
|
||||
if bytes.Equal(UID, sta.AdminUID) {
|
||||
finishHandshake := func() error {
|
||||
reply := server.ComposeReply(ch)
|
||||
_, err = conn.Write(reply)
|
||||
if err != nil {
|
||||
log.Printf("Sending reply to remote: %v\n", err)
|
||||
go conn.Close()
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
// Two discarded messages: ChangeCipherSpec and Finished
|
||||
|
|
@ -92,12 +92,19 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
|
|||
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
|
||||
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)
|
||||
for {
|
||||
n, err := conn.Read(data)
|
||||
|
|
@ -107,6 +114,7 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
|
|||
}
|
||||
resp, err := c.HandleRequest(data[:n])
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
_, 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 {
|
||||
log.Printf("+1 unauthorised user from %v, uid: %x\n", conn.RemoteAddr(), UID)
|
||||
goWeb(data)
|
||||
return
|
||||
}
|
||||
|
||||
reply := server.ComposeReply(ch)
|
||||
_, err = conn.Write(reply)
|
||||
err = finishHandshake()
|
||||
if err != nil {
|
||||
log.Printf("Sending reply to remote: %v\n", err)
|
||||
go conn.Close()
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
// Two discarded messages: ChangeCipherSpec and Finished
|
||||
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 {
|
||||
if sesh, existing := user.GetSession(sessionID, mux.MakeObfs(UID), mux.MakeDeobfs(UID), util.ReadTLS); existing {
|
||||
sesh.AddConnection(conn)
|
||||
return
|
||||
} 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.
|
||||
// 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) {
|
||||
h := xxhash.New32()
|
||||
ret := make([]uint32, 3)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ var ErrBrokenSession = errors.New("broken session")
|
|||
var errRepeatSessionClosing = errors.New("trying to close a closed session")
|
||||
|
||||
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
|
||||
obfs Obfser
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ type rawConfig struct {
|
|||
WebServerAddr string
|
||||
PrivateKey string
|
||||
AdminUID string
|
||||
SingleUser bool
|
||||
}
|
||||
type stateManager interface {
|
||||
ParseConfig(string) error
|
||||
|
|
|
|||
|
|
@ -65,13 +65,6 @@ func (u *User) updateInfo(uinfo UserInfo) {
|
|||
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) {
|
||||
u.sessionsM.Lock()
|
||||
u.sessions[sessionID] = sesh
|
||||
|
|
@ -89,7 +82,7 @@ func (u *User) DelSession(sessionID uint32) {
|
|||
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
|
||||
u.sessionsM.Lock()
|
||||
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 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
|
||||
|
||||
// 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 {
|
||||
return err
|
||||
}
|
||||
// FIXME: obnoxious code
|
||||
if err = b.Put([]byte("SessionsCap"), u32ToB(uinfo.SessionsCap)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue