Allow DatabasePath to be empty if user info database is never used

pull/148/head
Andy Wang 3 years ago
parent 298e6249e6
commit 0d3f8dd27f
No known key found for this signature in database
GPG Key ID: 181B49F9F38F3374

@ -103,15 +103,13 @@ Example:
`PrivateKey` is the static curve25519 Diffie-Hellman private key encoded in base64.
`AdminUID` is the UID of the admin user in base64.
`BypassUID` is a list of UIDs that are authorised without any bandwidth or credit limit restrictions
`DatabasePath` is the path to `userinfo.db`. If `userinfo.db` doesn't exist in this directory, Cloak will create one
automatically. **If Cloak is started as a Shadowsocks plugin and Shadowsocks is started with its working directory as
/ (e.g. starting ss-server with systemctl), you need to set this field as an absolute path to a desired folder. If you
leave it as default then Cloak will attempt to create userinfo.db under /, which it doesn't have the permission to do so
and will raise an error. See Issue #13.**
`AdminUID` is the UID of the admin user in base64. You can leave this empty if you only ever add users to `BypassUID`.
`DatabasePath` is the path to `userinfo.db`, which is used to store user usage information and restrictions. Cloak will
create the file automatically if it doesn't exist. You can leave this empty if you only ever add users to `BypassUID`.
This field also has no effect if `AdminUID` isn't a valid UID or is empty.
`KeepAlive` is the number of seconds to tell the OS to wait after no activity before sending TCP KeepAlive probes to the
upstream proxy server. Zero or negative value disables it. Default is 0 (disabled).
@ -184,6 +182,8 @@ Run `ck-server -uid` and add the UID into the `BypassUID` field in `ckserver.jso
##### Users subject to bandwidth and credit controls
0. First make sure you have `AdminUID` generated and set in `ckserver.json`, along with a path to `userinfo.db`
in `DatabasePath` (Cloak will create this file for you if it didn't already exist).
1. On your client, run `ck-client -s <IP of the server> -l <A local port> -a <AdminUID> -c <path-to-ckclient.json>` to
enter admin mode
2. Visit https://cbeuw.github.io/Cloak-panel (Note: this is a pure-js static site, there is no backend and all data

@ -143,9 +143,14 @@ func InitState(preParse RawConfig, worldState common.WorldState) (sta *State, er
err = errors.New("command & control mode not implemented")
return
} else {
manager, err := usermanager.MakeLocalManager(preParse.DatabasePath, worldState)
if err != nil {
return sta, err
var manager usermanager.UserManager
if len(preParse.AdminUID) == 0 || preParse.DatabasePath == "" {
manager = &usermanager.Voidmanager{}
} else {
manager, err = usermanager.MakeLocalManager(preParse.DatabasePath, worldState)
if err != nil {
return sta, err
}
}
sta.Panel = MakeUserPanel(manager)
}

@ -40,6 +40,7 @@ const (
var ErrUserNotFound = errors.New("UID does not correspond to a user")
var ErrSessionsCapReached = errors.New("Sessions cap has reached")
var ErrMangerIsVoid = errors.New("cannot perform operation with user manager as database path is not specified")
var ErrNoUpCredit = errors.New("No upload credit left")
var ErrNoDownCredit = errors.New("No download credit left")

@ -0,0 +1,31 @@
package usermanager
type Voidmanager struct{}
func (v *Voidmanager) AuthenticateUser(bytes []byte) (int64, int64, error) {
return 0, 0, ErrMangerIsVoid
}
func (v *Voidmanager) AuthoriseNewSession(bytes []byte, info AuthorisationInfo) error {
return ErrMangerIsVoid
}
func (v *Voidmanager) UploadStatus(updates []StatusUpdate) ([]StatusResponse, error) {
return nil, ErrMangerIsVoid
}
func (v *Voidmanager) ListAllUsers() ([]UserInfo, error) {
return nil, ErrMangerIsVoid
}
func (v *Voidmanager) GetUserInfo(UID []byte) (UserInfo, error) {
return UserInfo{}, ErrMangerIsVoid
}
func (v *Voidmanager) WriteUserInfo(info UserInfo) error {
return ErrMangerIsVoid
}
func (v *Voidmanager) DeleteUser(UID []byte) error {
return ErrMangerIsVoid
}

@ -0,0 +1,43 @@
package usermanager
import (
"github.com/stretchr/testify/assert"
"testing"
)
var v = &Voidmanager{}
func Test_Voidmanager_AuthenticateUser(t *testing.T) {
_, _, err := v.AuthenticateUser([]byte{})
assert.Equal(t, ErrMangerIsVoid, err)
}
func Test_Voidmanager_AuthoriseNewSession(t *testing.T) {
err := v.AuthoriseNewSession([]byte{}, AuthorisationInfo{})
assert.Equal(t, ErrMangerIsVoid, err)
}
func Test_Voidmanager_DeleteUser(t *testing.T) {
err := v.DeleteUser([]byte{})
assert.Equal(t, ErrMangerIsVoid, err)
}
func Test_Voidmanager_GetUserInfo(t *testing.T) {
_, err := v.GetUserInfo([]byte{})
assert.Equal(t, ErrMangerIsVoid, err)
}
func Test_Voidmanager_ListAllUsers(t *testing.T) {
_, err := v.ListAllUsers()
assert.Equal(t, ErrMangerIsVoid, err)
}
func Test_Voidmanager_UploadStatus(t *testing.T) {
_, err := v.UploadStatus([]StatusUpdate{})
assert.Equal(t, ErrMangerIsVoid, err)
}
func Test_Voidmanager_WriteUserInfo(t *testing.T) {
err := v.WriteUserInfo(UserInfo{})
assert.Equal(t, ErrMangerIsVoid, err)
}

@ -185,6 +185,9 @@ func (panel *userPanel) commitUpdate() error {
panel.usageUpdateQueue = make(map[[16]byte]*usagePair)
panel.usageUpdateQueueM.Unlock()
if len(statuses) == 0 {
return nil
}
responses, err := panel.Manager.UploadStatus(statuses)
if err != nil {
return err

@ -12,10 +12,8 @@ import (
"github.com/cbeuw/connutil"
"github.com/stretchr/testify/assert"
"io"
"io/ioutil"
"math/rand"
"net"
"os"
"sync"
"testing"
"time"
@ -24,8 +22,6 @@ import (
)
const numConns = 200 // -race option limits the number of goroutines to 8192
const delayBeforeTestingConnClose = 500 * time.Millisecond
const connCloseRetries = 3
func serveTCPEcho(l net.Listener) {
for {
@ -137,17 +133,15 @@ func generateClientConfigs(rawConfig client.RawConfig, state common.WorldState)
return lcl, rmt, auth
}
func basicServerState(ws common.WorldState, db *os.File) *server.State {
func basicServerState(ws common.WorldState) *server.State {
var serverConfig = server.RawConfig{
ProxyBook: map[string][]string{"shadowsocks": {"tcp", "fake.com:9999"}, "openvpn": {"udp", "fake.com:9999"}},
BindAddr: []string{"fake.com:9999"},
BypassUID: [][]byte{bypassUID[:]},
RedirAddr: "fake.com:9999",
PrivateKey: privateKey,
AdminUID: nil,
DatabasePath: db.Name(),
KeepAlive: 15,
CncMode: false,
ProxyBook: map[string][]string{"shadowsocks": {"tcp", "fake.com:9999"}, "openvpn": {"udp", "fake.com:9999"}},
BindAddr: []string{"fake.com:9999"},
BypassUID: [][]byte{bypassUID[:]},
RedirAddr: "fake.com:9999",
PrivateKey: privateKey,
KeepAlive: 15,
CncMode: false,
}
state, err := server.InitState(serverConfig, ws)
if err != nil {
@ -258,13 +252,11 @@ func runEchoTest(t *testing.T, conns []net.Conn, maxMsgLen int) {
}
func TestUDP(t *testing.T) {
var tmpDB, _ = ioutil.TempFile("", "ck_user_info")
defer os.Remove(tmpDB.Name())
log.SetLevel(log.ErrorLevel)
worldState := common.WorldOfTime(time.Unix(10, 0))
lcc, rcc, ai := generateClientConfigs(basicUDPConfig, worldState)
sta := basicServerState(worldState, tmpDB)
sta := basicServerState(worldState)
proxyToCkClientD, proxyFromCkServerL, _, _, err := establishSession(lcc, rcc, ai, sta)
if err != nil {
@ -319,9 +311,7 @@ func TestTCPSingleplex(t *testing.T) {
log.SetLevel(log.ErrorLevel)
worldState := common.WorldOfTime(time.Unix(10, 0))
lcc, rcc, ai := generateClientConfigs(singleplexTCPConfig, worldState)
var tmpDB, _ = ioutil.TempFile("", "ck_user_info")
defer os.Remove(tmpDB.Name())
sta := basicServerState(worldState, tmpDB)
sta := basicServerState(worldState)
proxyToCkClientD, proxyFromCkServerL, _, _, err := establishSession(lcc, rcc, ai, sta)
if err != nil {
t.Fatal(err)
@ -381,9 +371,7 @@ func TestTCPMultiplex(t *testing.T) {
worldState := common.WorldOfTime(time.Unix(10, 0))
lcc, rcc, ai := generateClientConfigs(basicTCPConfig, worldState)
var tmpDB, _ = ioutil.TempFile("", "ck_user_info")
defer os.Remove(tmpDB.Name())
sta := basicServerState(worldState, tmpDB)
sta := basicServerState(worldState)
proxyToCkClientD, proxyFromCkServerL, netToCkServerD, redirFromCkServerL, err := establishSession(lcc, rcc, ai, sta)
if err != nil {
@ -456,11 +444,8 @@ func TestClosingStreamsFromProxy(t *testing.T) {
clientConfig := clientConfig
clientConfigName := clientConfigName
t.Run(clientConfigName, func(t *testing.T) {
var tmpDB, _ = ioutil.TempFile("", "ck_user_info")
defer os.Remove(tmpDB.Name())
lcc, rcc, ai := generateClientConfigs(clientConfig, worldState)
sta := basicServerState(worldState, tmpDB)
sta := basicServerState(worldState)
proxyToCkClientD, proxyFromCkServerL, _, _, err := establishSession(lcc, rcc, ai, sta)
if err != nil {
t.Fatal(err)
@ -519,12 +504,10 @@ func TestClosingStreamsFromProxy(t *testing.T) {
}
func BenchmarkThroughput(b *testing.B) {
var tmpDB, _ = ioutil.TempFile("", "ck_user_info")
defer os.Remove(tmpDB.Name())
log.SetLevel(log.ErrorLevel)
worldState := common.WorldOfTime(time.Unix(10, 0))
lcc, rcc, ai := generateClientConfigs(basicTCPConfig, worldState)
sta := basicServerState(worldState, tmpDB)
sta := basicServerState(worldState)
const bufSize = 16 * 1024
encryptionMethods := map[string]byte{

Loading…
Cancel
Save