mirror of https://github.com/cbeuw/Cloak
Merge branch 'master' into notsure2
This commit is contained in:
commit
3155194ebe
|
|
@ -0,0 +1,17 @@
|
||||||
|
name: Build and test
|
||||||
|
on: [ push ]
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ ubuntu-latest, macos-latest, windows-latest ]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: '^1.15' # The Go version to download (if necessary) and use.
|
||||||
|
- run: go test -race -coverprofile coverage.txt -coverpkg ./... -covermode atomic ./...
|
||||||
|
- uses: codecov/codecov-action@v1
|
||||||
|
with:
|
||||||
|
file: coverage.txt
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
|
name: Create Release
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
export PATH=${PATH}:`go env GOPATH`/bin
|
||||||
|
v=${{ github.ref }} ./release.sh
|
||||||
|
- name: Release
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
files: release/*
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
10
.travis.yml
10
.travis.yml
|
|
@ -1,10 +0,0 @@
|
||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- "1.15"
|
|
||||||
|
|
||||||
script:
|
|
||||||
- go test -race -coverprofile=coverage.txt -coverpkg=./... -covermode=atomic ./...
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- bash <(curl -s https://codecov.io/bash)
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
[](https://travis-ci.org/cbeuw/Cloak)
|
[](https://github.com/cbeuw/Cloak/actions)
|
||||||
[](https://codecov.io/gh/cbeuw/Cloak)
|
[](https://codecov.io/gh/cbeuw/Cloak)
|
||||||
[](https://goreportcard.com/report/github.com/cbeuw/Cloak)
|
[](https://goreportcard.com/report/github.com/cbeuw/Cloak)
|
||||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=SAUYKGSREP8GL&source=url)
|
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=SAUYKGSREP8GL&source=url)
|
||||||
|
|
@ -165,9 +165,8 @@ is established.
|
||||||
|
|
||||||
0. Install at least one underlying proxy server (e.g. OpenVPN, Shadowsocks).
|
0. Install at least one underlying proxy server (e.g. OpenVPN, Shadowsocks).
|
||||||
1. Download [the latest release](https://github.com/cbeuw/Cloak/releases) or clone and build this repo.
|
1. Download [the latest release](https://github.com/cbeuw/Cloak/releases) or clone and build this repo.
|
||||||
2. Run `ck-server -k`. The base64 string before the comma is the **public** key to be given to users, the one after the
|
2. Run `ck-server -key`. The **public** should be given to users, the **private** key should be kept secret.
|
||||||
comma is the **private** key to be kept secret.
|
3. (Skip if you only want to add unrestricted users) Run `ck-server -uid`. The new UID will be used as `AdminUID`.
|
||||||
3. Run `ck-server -u`. This will be used as the `AdminUID`.
|
|
||||||
4. Copy example_config/ckserver.json into a desired location. Change `PrivateKey` to the private key you just obtained;
|
4. Copy example_config/ckserver.json into a desired location. Change `PrivateKey` to the private key you just obtained;
|
||||||
change `AdminUID` to the UID you just obtained.
|
change `AdminUID` to the UID you just obtained.
|
||||||
5. Configure your underlying proxy server so that they all listen on localhost. Edit `ProxyBook` in the configuration
|
5. Configure your underlying proxy server so that they all listen on localhost. Edit `ProxyBook` in the configuration
|
||||||
|
|
@ -181,7 +180,7 @@ is established.
|
||||||
|
|
||||||
##### Unrestricted users
|
##### Unrestricted users
|
||||||
|
|
||||||
Run `ck-server -u` and add the UID into the `BypassUID` field in `ckserver.json`
|
Run `ck-server -uid` and add the UID into the `BypassUID` field in `ckserver.json`
|
||||||
|
|
||||||
##### Users subject to bandwidth and credit controls
|
##### Users subject to bandwidth and credit controls
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
# Go
|
|
||||||
# Build your Go project.
|
|
||||||
# Add steps that test, save build artifacts, deploy, and more:
|
|
||||||
# https://docs.microsoft.com/azure/devops/pipelines/languages/go
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
tags:
|
|
||||||
include:
|
|
||||||
- refs/tags/v*
|
|
||||||
branches:
|
|
||||||
exclude:
|
|
||||||
- master
|
|
||||||
|
|
||||||
pool:
|
|
||||||
vmImage: 'ubuntu-latest'
|
|
||||||
|
|
||||||
variables:
|
|
||||||
GOBIN: '$(GOPATH)/bin' # Go binaries path
|
|
||||||
GOROOT: '$(Agent.BuildDirectory)/go' # Go installation path
|
|
||||||
GOPATH: '$(Agent.BuildDirectory)/gopath' # Go workspace path
|
|
||||||
modulePath: '$(GOPATH)/src/github.com/$(build.repository.name)' # Path to the module's code
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- script: |
|
|
||||||
mkdir -p '$(GOBIN)'
|
|
||||||
mkdir -p '$(GOPATH)/pkg'
|
|
||||||
mkdir -p '$(modulePath)'
|
|
||||||
shopt -s extglob
|
|
||||||
shopt -s dotglob
|
|
||||||
mv !(gopath) '$(modulePath)'
|
|
||||||
echo '##vso[task.prependpath]$(GOBIN)'
|
|
||||||
echo '##vso[task.prependpath]$(GOROOT)/bin'
|
|
||||||
wget "https://golang.org/dl/go1.15.2.linux-amd64.tar.gz" --output-document "$(Agent.BuildDirectory)/go1.15.2.tar.gz"
|
|
||||||
tar -C '$(Agent.BuildDirectory)' -xzf "$(Agent.BuildDirectory)/go1.15.2.tar.gz"
|
|
||||||
displayName: 'Set up the Go workspace'
|
|
||||||
|
|
||||||
- script: |
|
|
||||||
v="$(git describe --tags)" ./release.sh
|
|
||||||
mv ./release/* $(Build.ArtifactStagingDirectory)/
|
|
||||||
workingDirectory: '$(modulePath)'
|
|
||||||
displayName: 'Get dependencies, then build'
|
|
||||||
|
|
||||||
# GitHub Release
|
|
||||||
# Create, edit, or delete a GitHub release
|
|
||||||
- task: GitHubRelease@0
|
|
||||||
inputs:
|
|
||||||
gitHubConnection: github.com_cbeuw
|
|
||||||
repositoryName: '$(Build.Repository.Name)'
|
|
||||||
action: 'create' # Options: create, edit, delete
|
|
||||||
target: '$(Build.SourceVersion)' # Required when action == Create || Action == Edit
|
|
||||||
tagSource: 'auto' # Required when action == Create# Options: auto, manual
|
|
||||||
#tagPattern: # Optional
|
|
||||||
#tag: "$(git describe --tags)" # Required when action == Edit || Action == Delete || TagSource == Manual
|
|
||||||
#title: # Optional
|
|
||||||
#releaseNotesSource: 'file' # Optional. Options: file, input
|
|
||||||
#releaseNotesFile: # Optional
|
|
||||||
#releaseNotes: # Optional
|
|
||||||
#assets: '$(Build.ArtifactStagingDirectory)/*' # Optional
|
|
||||||
#assetUploadMode: 'delete' # Optional. Options: delete, replace
|
|
||||||
#isDraft: false # Optional
|
|
||||||
#isPreRelease: false # Optional
|
|
||||||
addChangeLog: false # Optional
|
|
||||||
#compareWith: 'lastFullRelease' # Required when addChangeLog == True. Options: lastFullRelease, lastRelease, lastReleaseByTag
|
|
||||||
#releaseTag: # Required when compareWith == LastReleaseByTag
|
|
||||||
|
|
@ -169,6 +169,7 @@ func main() {
|
||||||
}
|
}
|
||||||
log.Infof("Listening on %v %v for %v client", network, localConfig.LocalAddr, authInfo.ProxyMethod)
|
log.Infof("Listening on %v %v for %v client", network, localConfig.LocalAddr, authInfo.ProxyMethod)
|
||||||
seshMaker = func() *mux.Session {
|
seshMaker = func() *mux.Session {
|
||||||
|
authInfo := authInfo // copy the struct because we are overwriting SessionId
|
||||||
// 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.
|
||||||
quad := make([]byte, 4)
|
quad := make([]byte, 4)
|
||||||
|
|
|
||||||
|
|
@ -80,8 +80,11 @@ func main() {
|
||||||
askVersion := flag.Bool("v", false, "Print the version number")
|
askVersion := flag.Bool("v", false, "Print the version number")
|
||||||
printUsage := flag.Bool("h", false, "Print this message")
|
printUsage := flag.Bool("h", false, "Print this message")
|
||||||
|
|
||||||
genUID := flag.Bool("u", false, "Generate a UID")
|
genUIDScript := flag.Bool("u", false, "Generate a UID to STDOUT")
|
||||||
genKeyPair := flag.Bool("k", false, "Generate a pair of public and private key, output in the format of pubkey,pvkey")
|
genKeyPairScript := flag.Bool("k", false, "Generate a pair of public and private key and output to STDOUT in the format of <public key>,<private key>")
|
||||||
|
|
||||||
|
genUIDHuman := flag.Bool("uid", false, "Generate and print out a UID")
|
||||||
|
genKeyPairHuman := flag.Bool("key", false, "Generate and print out a public-private key pair")
|
||||||
|
|
||||||
pprofAddr := flag.String("d", "", "debug use: ip:port to be listened by pprof profiler")
|
pprofAddr := flag.String("d", "", "debug use: ip:port to be listened by pprof profiler")
|
||||||
verbosity := flag.String("verbosity", "info", "verbosity level")
|
verbosity := flag.String("verbosity", "info", "verbosity level")
|
||||||
|
|
@ -96,13 +99,23 @@ func main() {
|
||||||
flag.Usage()
|
flag.Usage()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if *genUID {
|
if *genUIDScript || *genUIDHuman {
|
||||||
fmt.Println(generateUID())
|
uid := generateUID()
|
||||||
|
if *genUIDScript {
|
||||||
|
fmt.Println(uid)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("\x1B[35mYour UID is:\u001B[0m %s\n", uid)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if *genKeyPair {
|
if *genKeyPairScript || *genKeyPairHuman {
|
||||||
pub, pv := generateKeyPair()
|
pub, pv := generateKeyPair()
|
||||||
fmt.Printf("%v,%v", pub, pv)
|
if *genKeyPairScript {
|
||||||
|
fmt.Printf("%v,%v\n", pub, pv)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("\x1B[36mYour PUBLIC key is:\x1B[0m %65s\n", pub)
|
||||||
|
fmt.Printf("\x1B[33mYour PRIVATE key is (keep it secret):\x1B[0m %47s\n", pv)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
"Transport": "direct",
|
"Transport": "direct",
|
||||||
"ProxyMethod": "shadowsocks",
|
"ProxyMethod": "shadowsocks",
|
||||||
"EncryptionMethod": "plain",
|
"EncryptionMethod": "plain",
|
||||||
"UID": "5nneblJy6lniPJfr81LuYQ==",
|
"UID": "---Your UID here---",
|
||||||
"PublicKey": "IYoUzkle/T/kriE+Ufdm7AHQtIeGnBWbhhlTbmDpUUI=",
|
"PublicKey": "---Public key here---",
|
||||||
"ServerName": "www.bing.com",
|
"ServerName": "www.bing.com",
|
||||||
"NumConn": 4,
|
"NumConn": 4,
|
||||||
"BrowserSig": "chrome",
|
"BrowserSig": "chrome",
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,10 @@
|
||||||
":80"
|
":80"
|
||||||
],
|
],
|
||||||
"BypassUID": [
|
"BypassUID": [
|
||||||
"1rmq6Ag1jZJCImLBIL5wzQ=="
|
"---Bypass UID here---"
|
||||||
],
|
],
|
||||||
"RedirAddr": "204.79.197.200:443",
|
"RedirAddr": "cloudflare.com",
|
||||||
"PrivateKey": "EN5aPEpNBO+vw+BtFQY2OnK9bQU7rvEj5qmnmgwEtUc=",
|
"PrivateKey": "---Private key here---",
|
||||||
"AdminUID": "5nneblJy6lniPJfr81LuYQ==",
|
"AdminUID": "---Admin UID here (optional)---",
|
||||||
"DatabasePath": "userinfo.db"
|
"DatabasePath": "userinfo.db"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
go.mod
2
go.mod
|
|
@ -15,7 +15,7 @@ require (
|
||||||
github.com/refraction-networking/utls v0.0.0-20190909200633-43c36d3c1f57
|
github.com/refraction-networking/utls v0.0.0-20190909200633-43c36d3c1f57
|
||||||
github.com/sirupsen/logrus v1.5.0
|
github.com/sirupsen/logrus v1.5.0
|
||||||
github.com/stephens2424/writerset v1.0.2 // indirect
|
github.com/stephens2424/writerset v1.0.2 // indirect
|
||||||
github.com/stretchr/testify v1.3.0
|
github.com/stretchr/testify v1.6.1
|
||||||
go.etcd.io/bbolt v1.3.4
|
go.etcd.io/bbolt v1.3.4
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
||||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 // indirect
|
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 // indirect
|
||||||
|
|
|
||||||
5
go.sum
5
go.sum
|
|
@ -43,6 +43,8 @@ github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
|
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
|
||||||
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||||
|
|
@ -76,5 +78,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
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=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func RouteUDP(bindFunc func() (*net.UDPConn, error), streamTimeout time.Duration, singleplex bool, newSeshFunc func() *mux.Session) {
|
func RouteUDP(bindFunc func() (*net.UDPConn, error), streamTimeout time.Duration, singleplex bool, newSeshFunc func() *mux.Session) {
|
||||||
var multiplexSession *mux.Session
|
var sesh *mux.Session
|
||||||
localConn, err := bindFunc()
|
localConn, err := bindFunc()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|
@ -27,25 +27,22 @@ func RouteUDP(bindFunc func() (*net.UDPConn, error), streamTimeout time.Duration
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !singleplex && (multiplexSession == nil || multiplexSession.IsClosed()) {
|
if !singleplex && (sesh == nil || sesh.IsClosed()) {
|
||||||
multiplexSession = newSeshFunc()
|
sesh = newSeshFunc()
|
||||||
}
|
}
|
||||||
|
|
||||||
stream, ok := streams[addr.String()]
|
stream, ok := streams[addr.String()]
|
||||||
if !ok {
|
if !ok {
|
||||||
var session *mux.Session
|
if singleplex {
|
||||||
if multiplexSession != nil {
|
sesh = newSeshFunc()
|
||||||
session = multiplexSession
|
|
||||||
} else {
|
|
||||||
session = newSeshFunc()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stream, err = session.OpenStream()
|
stream, err = sesh.OpenStream()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Failed to open stream: %v", err)
|
if singleplex {
|
||||||
if session.Singleplex {
|
sesh.Close()
|
||||||
session.Close()
|
|
||||||
}
|
}
|
||||||
|
log.Errorf("Failed to open stream: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,22 +79,19 @@ func RouteUDP(bindFunc func() (*net.UDPConn, error), streamTimeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func RouteTCP(listener net.Listener, streamTimeout time.Duration, singleplex bool, newSeshFunc func() *mux.Session) {
|
func RouteTCP(listener net.Listener, streamTimeout time.Duration, singleplex bool, newSeshFunc func() *mux.Session) {
|
||||||
var multiplexSession *mux.Session
|
var sesh *mux.Session
|
||||||
for {
|
for {
|
||||||
localConn, err := listener.Accept()
|
localConn, err := listener.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !singleplex && (multiplexSession == nil || multiplexSession.IsClosed()) {
|
if !singleplex && (sesh == nil || sesh.IsClosed()) {
|
||||||
multiplexSession = newSeshFunc()
|
sesh = newSeshFunc()
|
||||||
}
|
}
|
||||||
go func(multiplexSession *mux.Session, newSingleplexSeshFunc func() *mux.Session, localConn net.Conn, timeout time.Duration) {
|
go func(sesh *mux.Session, localConn net.Conn, timeout time.Duration) {
|
||||||
var session *mux.Session
|
if singleplex {
|
||||||
if multiplexSession != nil {
|
sesh = newSeshFunc()
|
||||||
session = multiplexSession
|
|
||||||
} else {
|
|
||||||
session = newSingleplexSeshFunc()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data := make([]byte, 10240)
|
data := make([]byte, 10240)
|
||||||
|
|
@ -115,8 +109,8 @@ func RouteTCP(listener net.Listener, streamTimeout time.Duration, singleplex boo
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Failed to open stream: %v", err)
|
log.Errorf("Failed to open stream: %v", err)
|
||||||
localConn.Close()
|
localConn.Close()
|
||||||
if session.Singleplex {
|
if singleplex {
|
||||||
session.Close()
|
sesh.Close()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ func TestDatagramBuffer_BlockingRead(t *testing.T) {
|
||||||
pipe := NewDatagramBufferedPipe()
|
pipe := NewDatagramBufferedPipe()
|
||||||
b := []byte{0x01, 0x02, 0x03}
|
b := []byte{0x01, 0x02, 0x03}
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(readBlockTime)
|
||||||
pipe.Write(Frame{Payload: b})
|
pipe.Write(Frame{Payload: b})
|
||||||
}()
|
}()
|
||||||
b2 := make([]byte, len(b))
|
b2 := make([]byte, len(b))
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/cbeuw/Cloak/internal/common"
|
"github.com/cbeuw/Cloak/internal/common"
|
||||||
"github.com/cbeuw/connutil"
|
"github.com/cbeuw/connutil"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"io"
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
|
|
@ -111,12 +112,14 @@ func TestMultiplex(t *testing.T) {
|
||||||
|
|
||||||
//test echo
|
//test echo
|
||||||
runEchoTest(t, streams, maxMsgLen)
|
runEchoTest(t, streams, maxMsgLen)
|
||||||
if clientSession.streamCount() != numStreams {
|
|
||||||
t.Errorf("client stream count is wrong: %v", clientSession.streamCount())
|
assert.Eventuallyf(t, func() bool {
|
||||||
}
|
return clientSession.streamCount() == numStreams
|
||||||
if serverSession.streamCount() != numStreams {
|
}, time.Second, 10*time.Millisecond, "client stream count is wrong: %v", clientSession.streamCount())
|
||||||
t.Errorf("server stream count is wrong: %v", serverSession.streamCount())
|
|
||||||
}
|
assert.Eventuallyf(t, func() bool {
|
||||||
|
return serverSession.streamCount() == numStreams
|
||||||
|
}, time.Second, 10*time.Millisecond, "server stream count is wrong: %v", serverSession.streamCount())
|
||||||
|
|
||||||
// close one stream
|
// close one stream
|
||||||
closing, streams := streams[0], streams[1:]
|
closing, streams := streams[0], streams[1:]
|
||||||
|
|
@ -148,9 +151,12 @@ func TestMux_StreamClosing(t *testing.T) {
|
||||||
t.Errorf("can't write to stream: %v", err)
|
t.Errorf("can't write to stream: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(500 * time.Millisecond)
|
_, err = io.ReadFull(toBeClosed, recvBuf[:1])
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("can't read anything before stream closed: %v", err)
|
||||||
|
}
|
||||||
_ = toBeClosed.Close()
|
_ = toBeClosed.Close()
|
||||||
_, err = io.ReadFull(toBeClosed, recvBuf)
|
_, err = io.ReadFull(toBeClosed, recvBuf[1:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("can't read residual data on stream: %v", err)
|
t.Errorf("can't read residual data on stream: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package multiplex
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/cbeuw/connutil"
|
"github.com/cbeuw/connutil"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
@ -408,10 +409,10 @@ func TestSession_timeoutAfter(t *testing.T) {
|
||||||
seshConfigOrdered.Obfuscator = obfuscator
|
seshConfigOrdered.Obfuscator = obfuscator
|
||||||
seshConfigOrdered.InactivityTimeout = 100 * time.Millisecond
|
seshConfigOrdered.InactivityTimeout = 100 * time.Millisecond
|
||||||
sesh := MakeSession(0, seshConfigOrdered)
|
sesh := MakeSession(0, seshConfigOrdered)
|
||||||
time.Sleep(200 * time.Millisecond)
|
|
||||||
if !sesh.IsClosed() {
|
assert.Eventually(t, func() bool {
|
||||||
t.Error("session should have timed out")
|
return sesh.IsClosed()
|
||||||
}
|
}, 5*seshConfigOrdered.InactivityTimeout, seshConfigOrdered.InactivityTimeout, "session should have timed out")
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkRecvDataFromRemote_Ordered(b *testing.B) {
|
func BenchmarkRecvDataFromRemote_Ordered(b *testing.B) {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const readBlockTime = 500 * time.Millisecond
|
||||||
|
|
||||||
func TestPipeRW(t *testing.T) {
|
func TestPipeRW(t *testing.T) {
|
||||||
pipe := NewStreamBufferedPipe()
|
pipe := NewStreamBufferedPipe()
|
||||||
b := []byte{0x01, 0x02, 0x03}
|
b := []byte{0x01, 0x02, 0x03}
|
||||||
|
|
@ -60,7 +62,7 @@ func TestReadBlock(t *testing.T) {
|
||||||
pipe := NewStreamBufferedPipe()
|
pipe := NewStreamBufferedPipe()
|
||||||
b := []byte{0x01, 0x02, 0x03}
|
b := []byte{0x01, 0x02, 0x03}
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(readBlockTime)
|
||||||
pipe.Write(b)
|
pipe.Write(b)
|
||||||
}()
|
}()
|
||||||
b2 := make([]byte, len(b))
|
b2 := make([]byte, len(b))
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package multiplex
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/cbeuw/Cloak/internal/common"
|
"github.com/cbeuw/Cloak/internal/common"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
|
@ -230,11 +231,11 @@ func TestStream_Close(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("can't read residual data %v", err)
|
t.Errorf("can't read residual data %v", err)
|
||||||
}
|
}
|
||||||
time.Sleep(100 * time.Millisecond)
|
|
||||||
if sI, _ := sesh.streams.Load(stream.(*Stream).id); sI != nil {
|
assert.Eventually(t, func() bool {
|
||||||
t.Error("stream still exists")
|
sI, _ := sesh.streams.Load(stream.(*Stream).id)
|
||||||
return
|
return sI == nil
|
||||||
}
|
}, time.Second, 10*time.Millisecond, "streams still exists")
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package multiplex
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/cbeuw/connutil"
|
"github.com/cbeuw/connutil"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -145,11 +146,11 @@ func TestSwitchboard_CloseOnOneDisconn(t *testing.T) {
|
||||||
sesh.AddConnection(conn1client)
|
sesh.AddConnection(conn1client)
|
||||||
|
|
||||||
conn0server.Close()
|
conn0server.Close()
|
||||||
time.Sleep(500 * time.Millisecond)
|
|
||||||
if !sesh.IsClosed() {
|
assert.Eventually(t, func() bool {
|
||||||
t.Error("session not closed after one conn is disconnected")
|
return sesh.IsClosed()
|
||||||
return
|
}, time.Second, 10*time.Millisecond, "session not closed after one conn is disconnected")
|
||||||
}
|
|
||||||
if _, err := conn1client.Write([]byte{0x00}); err == nil {
|
if _, err := conn1client.Write([]byte{0x00}); err == nil {
|
||||||
t.Error("the other conn is still connected")
|
t.Error("the other conn is still connected")
|
||||||
return
|
return
|
||||||
|
|
@ -178,9 +179,7 @@ func TestSwitchboard_ConnsCount(t *testing.T) {
|
||||||
|
|
||||||
sesh.sb.closeAll()
|
sesh.sb.closeAll()
|
||||||
|
|
||||||
time.Sleep(500 * time.Millisecond)
|
assert.Eventuallyf(t, func() bool {
|
||||||
if sesh.sb.connsCount() != 0 {
|
return sesh.sb.connsCount() == 0
|
||||||
t.Error("connsCount incorrect")
|
}, time.Second, 10*time.Millisecond, "connsCount incorrect: %v", sesh.sb.connsCount())
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ func dispatchConnection(conn net.Conn, sta *State) {
|
||||||
// adminUID can use the server as normal with unlimited QoS credits. The adminUID is not
|
// adminUID can use the server as normal with unlimited QoS credits. The adminUID is not
|
||||||
// added to the userinfo database. The distinction between going into the admin mode
|
// added to the userinfo database. The distinction between going into the admin mode
|
||||||
// and normal proxy mode is that sessionID needs == 0 for admin mode
|
// and normal proxy mode is that sessionID needs == 0 for admin mode
|
||||||
if bytes.Equal(ci.UID, sta.AdminUID) && ci.SessionId == 0 {
|
if len(sta.AdminUID) != 0 && bytes.Equal(ci.UID, sta.AdminUID) && ci.SessionId == 0 {
|
||||||
sesh := mux.MakeSession(0, seshConfig)
|
sesh := mux.MakeSession(0, seshConfig)
|
||||||
preparedConn, err := finishHandshake(conn, sessionKey, sta.WorldState.Rand)
|
preparedConn, err := finishHandshake(conn, sessionKey, sta.WorldState.Rand)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,10 @@ func InitState(preParse RawConfig, worldState common.WorldState) (sta *State, er
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(preParse.PrivateKey) == 0 {
|
||||||
|
err = fmt.Errorf("must have a valid private key. Run `ck-server -key` to generate one")
|
||||||
|
return
|
||||||
|
}
|
||||||
var pv [32]byte
|
var pv [32]byte
|
||||||
copy(pv[:], preParse.PrivateKey)
|
copy(pv[:], preParse.PrivateKey)
|
||||||
sta.StaticPv = &pv
|
sta.StaticPv = &pv
|
||||||
|
|
@ -179,8 +183,10 @@ func InitState(preParse RawConfig, worldState common.WorldState) (sta *State, er
|
||||||
copy(arrUID[:], UID)
|
copy(arrUID[:], UID)
|
||||||
sta.BypassUID[arrUID] = struct{}{}
|
sta.BypassUID[arrUID] = struct{}{}
|
||||||
}
|
}
|
||||||
copy(arrUID[:], sta.AdminUID)
|
if len(sta.AdminUID) != 0 {
|
||||||
sta.BypassUID[arrUID] = struct{}{}
|
copy(arrUID[:], sta.AdminUID)
|
||||||
|
sta.BypassUID[arrUID] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
go sta.UsedRandomCleaner()
|
go sta.UsedRandomCleaner()
|
||||||
return sta, nil
|
return sta, nil
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,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/connutil"
|
"github.com/cbeuw/connutil"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
|
@ -185,7 +186,9 @@ func establishSession(lcc client.LocalConnConfig, rcc client.RemoteConnConfig, a
|
||||||
// whatever connection initiator (including a proper ck-client)
|
// whatever connection initiator (including a proper ck-client)
|
||||||
|
|
||||||
netToCkServerD, ckServerListener := connutil.DialerListener(10 * 1024)
|
netToCkServerD, ckServerListener := connutil.DialerListener(10 * 1024)
|
||||||
|
|
||||||
clientSeshMaker := func() *mux.Session {
|
clientSeshMaker := func() *mux.Session {
|
||||||
|
ai := ai
|
||||||
quad := make([]byte, 4)
|
quad := make([]byte, 4)
|
||||||
common.RandRead(ai.WorldState.Rand, quad)
|
common.RandRead(ai.WorldState.Rand, quad)
|
||||||
ai.SessionId = binary.BigEndian.Uint32(quad)
|
ai.SessionId = binary.BigEndian.Uint32(quad)
|
||||||
|
|
@ -354,17 +357,9 @@ func TestTCPSingleplex(t *testing.T) {
|
||||||
|
|
||||||
proxyConn1.Close()
|
proxyConn1.Close()
|
||||||
|
|
||||||
retries := 0
|
assert.Eventually(t, func() bool {
|
||||||
retry:
|
return user.NumSession() == 1
|
||||||
time.Sleep(delayBeforeTestingConnClose)
|
}, time.Second, 10*time.Millisecond, "first session was not closed on connection close")
|
||||||
if user.NumSession() != 1 {
|
|
||||||
retries++
|
|
||||||
if retries > connCloseRetries {
|
|
||||||
t.Error("first session was not closed on connection close")
|
|
||||||
} else {
|
|
||||||
goto retry
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// conn2 should still work
|
// conn2 should still work
|
||||||
runEchoTest(t, []net.Conn{proxyConn2}, 65536)
|
runEchoTest(t, []net.Conn{proxyConn2}, 65536)
|
||||||
|
|
@ -477,17 +472,10 @@ func TestClosingStreamsFromProxy(t *testing.T) {
|
||||||
serverConn, _ := proxyFromCkServerL.Accept()
|
serverConn, _ := proxyFromCkServerL.Accept()
|
||||||
serverConn.Close()
|
serverConn.Close()
|
||||||
|
|
||||||
retries := 0
|
assert.Eventually(t, func() bool {
|
||||||
retry:
|
_, err := clientConn.Read(make([]byte, 16))
|
||||||
time.Sleep(delayBeforeTestingConnClose)
|
return err != nil
|
||||||
if _, err := clientConn.Read(make([]byte, 16)); err == nil {
|
}, time.Second, 10*time.Millisecond, "closing stream on server side is not reflected to the client")
|
||||||
retries++
|
|
||||||
if retries > connCloseRetries {
|
|
||||||
t.Errorf("closing stream on server side is not reflected to the client: %v", err)
|
|
||||||
} else {
|
|
||||||
goto retry
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("closing from client", func(t *testing.T) {
|
t.Run("closing from client", func(t *testing.T) {
|
||||||
|
|
@ -497,17 +485,10 @@ func TestClosingStreamsFromProxy(t *testing.T) {
|
||||||
serverConn, _ := proxyFromCkServerL.Accept()
|
serverConn, _ := proxyFromCkServerL.Accept()
|
||||||
clientConn.Close()
|
clientConn.Close()
|
||||||
|
|
||||||
retries := 0
|
assert.Eventually(t, func() bool {
|
||||||
retry:
|
_, err := serverConn.Read(make([]byte, 16))
|
||||||
time.Sleep(delayBeforeTestingConnClose)
|
return err != nil
|
||||||
if _, err := serverConn.Read(make([]byte, 16)); err == nil {
|
}, time.Second, 10*time.Millisecond, "closing stream on client side is not reflected to the server")
|
||||||
retries++
|
|
||||||
if retries > 3 {
|
|
||||||
t.Errorf("closing stream on client side is not reflected to the server: %v", err)
|
|
||||||
} else {
|
|
||||||
goto retry
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("send then close", func(t *testing.T) {
|
t.Run("send then close", func(t *testing.T) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue