Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Yrr0r committed May 16, 2018
0 parents commit e8457cc
Show file tree
Hide file tree
Showing 17 changed files with 789 additions and 0 deletions.
Binary file added .DS_Store
Binary file not shown.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2018 Yrr0r

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
54 changes: 54 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//CLIENT

package main

import (
"fmt"
"log"
"net"

"./cmd"
"./core"
"./local"
)

var version = "master"

func main() {
fmt.Print("Ich*Liebe*Dich~ \n", "CLIENT\n")
log.SetFlags(log.Lshortfile)

// 默认配置
config := &cmd.Config{
ListenAddr: ":7448",
}
config.ReadConfig()

// 解析配置
password, err := core.ParsePassword(config.Password)
if err != nil {
log.Fatalln(err)
}
listenAddr, err := net.ResolveTCPAddr("tcp", config.ListenAddr)
if err != nil {
log.Fatalln(err)
}
remoteAddr, err := net.ResolveTCPAddr("tcp", config.RemoteAddr)
if err != nil {
log.Fatalln(err)
}

// 启动 local 端并监听
lsLocal := local.New(password, listenAddr, remoteAddr)
log.Fatalln(lsLocal.Listen(func(listenAddr net.Addr) {
log.Println("使用配置:", fmt.Sprintf(`
本地监听地址 listen:
%s
远程服务地址 remote:
%s
密码 password:
%s
`, listenAddr, remoteAddr, password))
log.Printf("lightsocks-local:%s 启动成功 监听在 %s\n", version, listenAddr.String())
}))
}
Binary file added cmd/.DS_Store
Binary file not shown.
103 changes: 103 additions & 0 deletions cmd/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package cmd

import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"path"

"flag"

"../core"
)

var (
// 配置文件路径
configPath string
)

var listen string
var passwd string
var remote string

//Config temporary structure
type Config struct {
ListenAddr string `json:"listen"`
RemoteAddr string `json:"remote"`
Password string `json:"password"`
}

func init() {

flag.StringVar(&configPath, "conf", "NO", "配置文件路径")

flag.StringVar(&listen, "port", "EMPTY", "服务器端口")
flag.StringVar(&passwd, "pass", "EMPTY", "密码")
flag.StringVar(&remote, "remote", "EMPTY", "remote")

var confgen = flag.String("gconf", "NO", "用此命令生成配置文件然后手动填入参数。")

flag.Usage = func() {
flag.PrintDefaults()
}

flag.Parse()

if *confgen != "NO" {
configPath = *confgen
content := Config{
ListenAddr: ":7448",
// 密码随机生成
Password: core.RandPassword().String(),
}
configJson, _ := json.MarshalIndent(content, "", " ")
err := ioutil.WriteFile(configPath, configJson, 0644)
if err != nil {
fmt.Errorf("保存配置到文件出错: ", configPath, err)
}
log.Printf("保存配置到文件成功", configPath, "\n")
os.Exit(0)
}
if configPath == "NO" {
file, err := os.Getwd()
configPath = path.Join(file, "conf.json")
fmt.Println(configPath)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}

}

func (config *Config) ReadConfig() {
// 如果配置文件存在,就读取配置文件中的配置 assign 到 config
if _, err := os.Stat(configPath); !os.IsNotExist(err) {
log.Printf("读取配置:", configPath, "\n")
file, err := os.Open(configPath)
if err != nil {
log.Fatalf("打开配置文件 %s 出错:%s", configPath, err)
}
defer file.Close()

err = json.NewDecoder(file).Decode(config)
if err != nil {
log.Fatalf("格式不合法的 JSON 配置文件:\n%s", file)
}
}
if listen != "EMPTY" {
config.ListenAddr = ":" + listen
fmt.Println("端口:命令行参数先于配置文件")
}
if passwd != "EMPTY" {
config.Password = passwd
fmt.Println("密码:命令行参数先于配置文件")
}
if remote != "EMPTY" {
config.RemoteAddr = remote
fmt.Println("Remote:命令行参数先于配置文件")
}

}
35 changes: 35 additions & 0 deletions core/cipher.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package core

type Cipher struct {
// 编码用的密码
encodePassword *Password
// 解码用的密码
decodePassword *Password
}

// 加密原数据
func (cipher *Cipher) encode(bs []byte) {
for i, v := range bs {
bs[i] = cipher.encodePassword[v]
}
}

// 解码加密后的数据到原数据
func (cipher *Cipher) decode(bs []byte) {
for i, v := range bs {
bs[i] = cipher.decodePassword[v]
}
}

// 新建一个编码解码器
func NewCipher(encodePassword *Password) *Cipher {
decodePassword := &Password{}
for i, v := range encodePassword {
encodePassword[i] = v
decodePassword[v] = byte(i)
}
return &Cipher{
encodePassword: encodePassword,
decodePassword: decodePassword,
}
}
54 changes: 54 additions & 0 deletions core/cipher_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package core

import (
"crypto/rand"
"reflect"
"testing"
)

const (
MB = 1024 * 1024
)

// 测试 Cipher 加密解密
func TestCipher(t *testing.T) {
password := RandPassword()
t.Log(password)
cipher := NewCipher(password)
// 原数据
org := make([]byte, PasswordLength)
for i := 0; i < PasswordLength; i++ {
org[i] = byte(i)
}
// 复制一份原数据到 tmp
tmp := make([]byte, PasswordLength)
copy(tmp, org)
t.Log(tmp)
// 加密 tmp
cipher.encode(tmp)
t.Log(tmp)
// 解密 tmp
cipher.decode(tmp)
t.Log(tmp)
if !reflect.DeepEqual(org, tmp) {
t.Error("解码编码数据后无法还原数据,数据不对应")
}
}

func BenchmarkEncode(b *testing.B) {
password := RandPassword()
cipher := NewCipher(password)
bs := make([]byte, MB)
b.ResetTimer()
rand.Read(bs)
cipher.encode(bs)
}

func BenchmarkDecode(b *testing.B) {
password := RandPassword()
cipher := NewCipher(password)
bs := make([]byte, MB)
b.ResetTimer()
rand.Read(bs)
cipher.decode(bs)
}
53 changes: 53 additions & 0 deletions core/password.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package core

import (
"encoding/base64"
"errors"
"math/rand"
"strings"
"time"
)

const PasswordLength = 256

var ErrInvalidPassword = errors.New("不合法的密码")

type Password [PasswordLength]byte

func init() {
// 更新随机种子,防止生成一样的随机密码
rand.Seed(time.Now().Unix())
}

// 采用base64编码把密码转换为字符串
func (password *Password) String() string {
return base64.StdEncoding.EncodeToString(password[:])
}

// 解析采用base64编码的字符串获取密码
func ParsePassword(passwordString string) (*Password, error) {
bs, err := base64.StdEncoding.DecodeString(strings.TrimSpace(passwordString))
if err != nil || len(bs) != PasswordLength {
return nil, ErrInvalidPassword
}
password := Password{}
copy(password[:], bs)
bs = nil
return &password, nil
}

// 产生 256个byte随机组合的 密码,最后会使用base64编码为字符串存储在配置文件中
// 不能出现任何一个重复的byte位,必须又 0-255 组成,并且都需要包含
func RandPassword() *Password {
// 随机生成一个由 0~255 组成的 byte 数组
intArr := rand.Perm(PasswordLength)
password := &Password{}
for i, v := range intArr {
password[i] = byte(v)
if i == v {
// 确保不会出现如何一个byte位出现重复
return RandPassword()
}
}
return password
}
43 changes: 43 additions & 0 deletions core/password_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package core

import (
"reflect"
"sort"
"testing"
)

func (password *Password) Len() int {
return PasswordLength
}

func (password *Password) Less(i, j int) bool {
return password[i] < password[j]
}

func (password *Password) Swap(i, j int) {
password[i], password[j] = password[j], password[i]
}

func TestRandPassword(t *testing.T) {
password := RandPassword()
t.Log(password)
sort.Sort(password)
for i := 0; i < PasswordLength; i++ {
if password[i] != byte(i) {
t.Error("不能出现任何一个重复的byte位,必须由 0-255 组成,并且都需要包含")
}
}
}

func TestPasswordString(t *testing.T) {
password := RandPassword()
passwordStr := password.String()
decodePassword, err := ParsePassword(passwordStr)
if err != nil {
t.Error(err)
} else {
if !reflect.DeepEqual(password, decodePassword) {
t.Error("密码转化成字符串后反解后数据不对应")
}
}
}
Loading

0 comments on commit e8457cc

Please sign in to comment.