Skip to content

Commit e8457cc

Browse files
committed
Initial commit
0 parents  commit e8457cc

17 files changed

+789
-0
lines changed

.DS_Store

12 KB
Binary file not shown.

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2018 Yrr0r
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

client.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//CLIENT
2+
3+
package main
4+
5+
import (
6+
"fmt"
7+
"log"
8+
"net"
9+
10+
"./cmd"
11+
"./core"
12+
"./local"
13+
)
14+
15+
var version = "master"
16+
17+
func main() {
18+
fmt.Print("Ich*Liebe*Dich~ \n", "CLIENT\n")
19+
log.SetFlags(log.Lshortfile)
20+
21+
// 默认配置
22+
config := &cmd.Config{
23+
ListenAddr: ":7448",
24+
}
25+
config.ReadConfig()
26+
27+
// 解析配置
28+
password, err := core.ParsePassword(config.Password)
29+
if err != nil {
30+
log.Fatalln(err)
31+
}
32+
listenAddr, err := net.ResolveTCPAddr("tcp", config.ListenAddr)
33+
if err != nil {
34+
log.Fatalln(err)
35+
}
36+
remoteAddr, err := net.ResolveTCPAddr("tcp", config.RemoteAddr)
37+
if err != nil {
38+
log.Fatalln(err)
39+
}
40+
41+
// 启动 local 端并监听
42+
lsLocal := local.New(password, listenAddr, remoteAddr)
43+
log.Fatalln(lsLocal.Listen(func(listenAddr net.Addr) {
44+
log.Println("使用配置:", fmt.Sprintf(`
45+
本地监听地址 listen:
46+
%s
47+
远程服务地址 remote:
48+
%s
49+
密码 password:
50+
%s
51+
`, listenAddr, remoteAddr, password))
52+
log.Printf("lightsocks-local:%s 启动成功 监听在 %s\n", version, listenAddr.String())
53+
}))
54+
}

cmd/.DS_Store

6 KB
Binary file not shown.

cmd/config.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package cmd
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io/ioutil"
7+
"log"
8+
"os"
9+
"path"
10+
11+
"flag"
12+
13+
"../core"
14+
)
15+
16+
var (
17+
// 配置文件路径
18+
configPath string
19+
)
20+
21+
var listen string
22+
var passwd string
23+
var remote string
24+
25+
//Config temporary structure
26+
type Config struct {
27+
ListenAddr string `json:"listen"`
28+
RemoteAddr string `json:"remote"`
29+
Password string `json:"password"`
30+
}
31+
32+
func init() {
33+
34+
flag.StringVar(&configPath, "conf", "NO", "配置文件路径")
35+
36+
flag.StringVar(&listen, "port", "EMPTY", "服务器端口")
37+
flag.StringVar(&passwd, "pass", "EMPTY", "密码")
38+
flag.StringVar(&remote, "remote", "EMPTY", "remote")
39+
40+
var confgen = flag.String("gconf", "NO", "用此命令生成配置文件然后手动填入参数。")
41+
42+
flag.Usage = func() {
43+
flag.PrintDefaults()
44+
}
45+
46+
flag.Parse()
47+
48+
if *confgen != "NO" {
49+
configPath = *confgen
50+
content := Config{
51+
ListenAddr: ":7448",
52+
// 密码随机生成
53+
Password: core.RandPassword().String(),
54+
}
55+
configJson, _ := json.MarshalIndent(content, "", " ")
56+
err := ioutil.WriteFile(configPath, configJson, 0644)
57+
if err != nil {
58+
fmt.Errorf("保存配置到文件出错: ", configPath, err)
59+
}
60+
log.Printf("保存配置到文件成功", configPath, "\n")
61+
os.Exit(0)
62+
}
63+
if configPath == "NO" {
64+
file, err := os.Getwd()
65+
configPath = path.Join(file, "conf.json")
66+
fmt.Println(configPath)
67+
if err != nil {
68+
fmt.Println(err)
69+
os.Exit(1)
70+
}
71+
}
72+
73+
}
74+
75+
func (config *Config) ReadConfig() {
76+
// 如果配置文件存在,就读取配置文件中的配置 assign 到 config
77+
if _, err := os.Stat(configPath); !os.IsNotExist(err) {
78+
log.Printf("读取配置:", configPath, "\n")
79+
file, err := os.Open(configPath)
80+
if err != nil {
81+
log.Fatalf("打开配置文件 %s 出错:%s", configPath, err)
82+
}
83+
defer file.Close()
84+
85+
err = json.NewDecoder(file).Decode(config)
86+
if err != nil {
87+
log.Fatalf("格式不合法的 JSON 配置文件:\n%s", file)
88+
}
89+
}
90+
if listen != "EMPTY" {
91+
config.ListenAddr = ":" + listen
92+
fmt.Println("端口:命令行参数先于配置文件")
93+
}
94+
if passwd != "EMPTY" {
95+
config.Password = passwd
96+
fmt.Println("密码:命令行参数先于配置文件")
97+
}
98+
if remote != "EMPTY" {
99+
config.RemoteAddr = remote
100+
fmt.Println("Remote:命令行参数先于配置文件")
101+
}
102+
103+
}

core/cipher.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package core
2+
3+
type Cipher struct {
4+
// 编码用的密码
5+
encodePassword *Password
6+
// 解码用的密码
7+
decodePassword *Password
8+
}
9+
10+
// 加密原数据
11+
func (cipher *Cipher) encode(bs []byte) {
12+
for i, v := range bs {
13+
bs[i] = cipher.encodePassword[v]
14+
}
15+
}
16+
17+
// 解码加密后的数据到原数据
18+
func (cipher *Cipher) decode(bs []byte) {
19+
for i, v := range bs {
20+
bs[i] = cipher.decodePassword[v]
21+
}
22+
}
23+
24+
// 新建一个编码解码器
25+
func NewCipher(encodePassword *Password) *Cipher {
26+
decodePassword := &Password{}
27+
for i, v := range encodePassword {
28+
encodePassword[i] = v
29+
decodePassword[v] = byte(i)
30+
}
31+
return &Cipher{
32+
encodePassword: encodePassword,
33+
decodePassword: decodePassword,
34+
}
35+
}

core/cipher_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package core
2+
3+
import (
4+
"crypto/rand"
5+
"reflect"
6+
"testing"
7+
)
8+
9+
const (
10+
MB = 1024 * 1024
11+
)
12+
13+
// 测试 Cipher 加密解密
14+
func TestCipher(t *testing.T) {
15+
password := RandPassword()
16+
t.Log(password)
17+
cipher := NewCipher(password)
18+
// 原数据
19+
org := make([]byte, PasswordLength)
20+
for i := 0; i < PasswordLength; i++ {
21+
org[i] = byte(i)
22+
}
23+
// 复制一份原数据到 tmp
24+
tmp := make([]byte, PasswordLength)
25+
copy(tmp, org)
26+
t.Log(tmp)
27+
// 加密 tmp
28+
cipher.encode(tmp)
29+
t.Log(tmp)
30+
// 解密 tmp
31+
cipher.decode(tmp)
32+
t.Log(tmp)
33+
if !reflect.DeepEqual(org, tmp) {
34+
t.Error("解码编码数据后无法还原数据,数据不对应")
35+
}
36+
}
37+
38+
func BenchmarkEncode(b *testing.B) {
39+
password := RandPassword()
40+
cipher := NewCipher(password)
41+
bs := make([]byte, MB)
42+
b.ResetTimer()
43+
rand.Read(bs)
44+
cipher.encode(bs)
45+
}
46+
47+
func BenchmarkDecode(b *testing.B) {
48+
password := RandPassword()
49+
cipher := NewCipher(password)
50+
bs := make([]byte, MB)
51+
b.ResetTimer()
52+
rand.Read(bs)
53+
cipher.decode(bs)
54+
}

core/password.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package core
2+
3+
import (
4+
"encoding/base64"
5+
"errors"
6+
"math/rand"
7+
"strings"
8+
"time"
9+
)
10+
11+
const PasswordLength = 256
12+
13+
var ErrInvalidPassword = errors.New("不合法的密码")
14+
15+
type Password [PasswordLength]byte
16+
17+
func init() {
18+
// 更新随机种子,防止生成一样的随机密码
19+
rand.Seed(time.Now().Unix())
20+
}
21+
22+
// 采用base64编码把密码转换为字符串
23+
func (password *Password) String() string {
24+
return base64.StdEncoding.EncodeToString(password[:])
25+
}
26+
27+
// 解析采用base64编码的字符串获取密码
28+
func ParsePassword(passwordString string) (*Password, error) {
29+
bs, err := base64.StdEncoding.DecodeString(strings.TrimSpace(passwordString))
30+
if err != nil || len(bs) != PasswordLength {
31+
return nil, ErrInvalidPassword
32+
}
33+
password := Password{}
34+
copy(password[:], bs)
35+
bs = nil
36+
return &password, nil
37+
}
38+
39+
// 产生 256个byte随机组合的 密码,最后会使用base64编码为字符串存储在配置文件中
40+
// 不能出现任何一个重复的byte位,必须又 0-255 组成,并且都需要包含
41+
func RandPassword() *Password {
42+
// 随机生成一个由 0~255 组成的 byte 数组
43+
intArr := rand.Perm(PasswordLength)
44+
password := &Password{}
45+
for i, v := range intArr {
46+
password[i] = byte(v)
47+
if i == v {
48+
// 确保不会出现如何一个byte位出现重复
49+
return RandPassword()
50+
}
51+
}
52+
return password
53+
}

core/password_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package core
2+
3+
import (
4+
"reflect"
5+
"sort"
6+
"testing"
7+
)
8+
9+
func (password *Password) Len() int {
10+
return PasswordLength
11+
}
12+
13+
func (password *Password) Less(i, j int) bool {
14+
return password[i] < password[j]
15+
}
16+
17+
func (password *Password) Swap(i, j int) {
18+
password[i], password[j] = password[j], password[i]
19+
}
20+
21+
func TestRandPassword(t *testing.T) {
22+
password := RandPassword()
23+
t.Log(password)
24+
sort.Sort(password)
25+
for i := 0; i < PasswordLength; i++ {
26+
if password[i] != byte(i) {
27+
t.Error("不能出现任何一个重复的byte位,必须由 0-255 组成,并且都需要包含")
28+
}
29+
}
30+
}
31+
32+
func TestPasswordString(t *testing.T) {
33+
password := RandPassword()
34+
passwordStr := password.String()
35+
decodePassword, err := ParsePassword(passwordStr)
36+
if err != nil {
37+
t.Error(err)
38+
} else {
39+
if !reflect.DeepEqual(password, decodePassword) {
40+
t.Error("密码转化成字符串后反解后数据不对应")
41+
}
42+
}
43+
}

0 commit comments

Comments
 (0)