Skip to content

Commit

Permalink
初版服务端完成,有很多bug
Browse files Browse the repository at this point in the history
  • Loading branch information
maxlv7 committed Apr 12, 2020
1 parent 29a1d9c commit ba426a1
Show file tree
Hide file tree
Showing 11 changed files with 323 additions and 134 deletions.
18 changes: 12 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10)
project(LightSocks)

set(CMAKE_CXX_STANDARD 11)
aux_source_directory(. SOURCE_CODE)
#aux_source_directory(. SOURCE_CODE)

include_directories(lib/json)
IF (WIN32)
Expand All @@ -17,18 +17,24 @@ IF (WIN32)
ELSEIF (UNIX)
link_directories(/usr/lib)
ENDIF ()
add_subdirectory(lib/base64)

#添加子库
add_subdirectory(lib/base64)

add_executable(LightSocksClient-cpp ${SOURCE_CODE})
#add_executable(LightSocks-client ${SOURCE_CODE})
add_executable(LightSocks-client main_client.cpp client.cpp util.cpp)
add_executable(LightSocks-server main_server.cpp server.cpp util cipher.cpp)

target_link_libraries(LightSocksClient-cpp base64)
target_link_libraries(LightSocks-client base64)
target_link_libraries(LightSocks-server base64)

IF (WIN32)
target_link_libraries(LightSocksClient-cpp event.lib)
target_link_libraries(LightSocks-client event.lib)
target_link_libraries(LightSocks-server event.lib)
ELSEIF (APPLE)
MESSAGE(STATUS "Now is Apple systems.")
ELSEIF (UNIX)
MESSAGE(STATUS "Now is UNIX-like OS's. Including aPPLE os x and CygWin")
target_link_libraries(LightSocksClient-cpp event)
target_link_libraries(LightSocks-client event)
target_link_libraries(LightSocks-server event)
ENDIF ()
48 changes: 37 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@
一个轻量级网络混淆代理,基于 SOCKS5 协议,可用来代替 Shadowsocks(?)。

- 只专注于混淆,用最简单高效的混淆算法达到目的;
- 基于c++ 11实现,使用高效的[libevent](https://github.com/libevent/libevent)网络库;
- 基于`c++ 11`实现,使用高效的[libevent](https://github.com/libevent/libevent)网络库;
- 使用`cmake`构建,方便实现跨平台

> 本项目为 [你也能写个 Shadowsocks](https://github.com/gwuhaolin/blog/issues/12) 的 c++ 实现
> 作者实现了 GO 版本 **[Lightsocks](https://github.com/gwuhaolin/lightsocks)**
> **重要提示:目前只实现了client,服务端正在开发之中...**
> **c++初学者,代码写的不好,多多海涵~**
> **代码写的不好,多多海涵~**
# 编译
## CMake (Windows)
## 编译
### CMake (Windows)

Install CMake: <https://www.cmake.org>
针对windows的编译安装,我已经提供了libevent2.1.11的64位编译版本,位于lib/event
Expand All @@ -24,23 +23,29 @@ $ cmake --build . --config Release
```

## CMake (Linux)
### CMake (Linux)
请先安装libevent2.1.11
<https://github.com/libevent/libevent>
Linux:克隆本项目<https://github.com/maxlv7/LightSocks-cxx.git>,进入项目主目录。
```
$ mkdir build && cd build
$ cmake ..
$ make
```
# 使用
如果不出意外的话,将会在当前目录下生成两个可执行文件:`LightSocks-client``LightSocks-server`

## 使用

### 客户端使用
直接运行生成的可执行文件,程序会自动读取当前目录下的config.json
如果没有config.json文件,那么程序会在当前目录下自动生成config.json
其各字段含义如下:

```
{
"ip": "23.102.255.234", //远程服务器地址
"remote_port": 7009, //远程服务器端口
"local_port": 7878, //监听的本地地址
"listen_port": 7878, //监听的本地地址
"password": "******" //密码
}
```
Expand All @@ -53,8 +58,24 @@ $ make
[2020-04-02 14:55:25.968] [info] 读取到远程端口:7009
[2020-04-02 14:55:25.969] [info] 成功监听地址-->socks5://127.0.0.1:7878
```

## 感谢
### 服务端使用
直接运行生成的可执行文件,程序会自动读取当前目录下的config_server.json
如果没有config_server.json文件,那么程序会在当前目录下自动生成默认的config_server.json
其各字段含义如下:
```
{
"listen_port": 7009, //监听的本地地址
"password": "******" //密码
}
```
如果一切配置无误,那么启动程序就会看到:
```
[2020-04-12 16:25:28.212] [info] 成功加载配置文件[config_server.json]
[2020-04-12 16:25:28.213] [info] 读取到监听地址:[::]:7009
[2020-04-12 16:25:28.213] [info] 读取到密码:nq9Bib/tgSfiVvrRPjWUU9PCcRnmBKBiLSkF3brP9PnwxH5lDYymyd+7zB7hKKg6nypHSI37vFTjrYPXWAn9iuTvZqm9sR9tW6IsTzzVsEpXkRQBLtyVcxrn+EP+QpaX6wOOUPak26Px1CE22CIHC6XKrg8xAIa589rlzaclThAwFXmHMjOEmCZG2ZxfwUSS6qx6aXhgbvfgqky2cFWba5DpyIUdxQw7OS9kG2rWBn+Pi4KyAkB3P7j1UfxJiG8gtxhsNwo0DscrzrPuOKGZq3VLJJqTXF59XXLyWXydY+xoEcN26BwXI4BSy7XGEwj/Ft6+PRJ0Z3vARdJN0FphtA==
[2020-04-12 16:25:28.214] [info] 监听在: 127.0.0.1:7009
```
## 特别感谢
<https://github.com/libevent/libevent>

<https://github.com/gwuhaolin/lightsocks>
Expand All @@ -67,3 +88,8 @@ $ make

<https://github.com/LeeReindeer/lightsocks-c>

<https://github.com/gabime/spdlog>

## 已知问题
1. server端内存泄漏(原因不明)

69 changes: 69 additions & 0 deletions cipher.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//
// Created by Li on 2020/4/9.
//

#include "cipher.h"


void Cipher::decrypt(bufferevent *self, bufferevent *partner) {
unsigned char d_password[256] = {0};
for (auto i = 0; i < 256; i++) {
d_password[Cipher::password[i]] = i;
}
while (true) {
unsigned char encode_data[1024]{0};
auto data_len = bufferevent_read(self, encode_data, sizeof(encode_data) - 1);
if (data_len <= 0) {
break;
}
unsigned char temp_data[1024]{0};
for (auto i = 0; i < data_len; i++) {
temp_data[i] = d_password[encode_data[i]];
}
bufferevent_write(partner, temp_data, data_len);
}
}

void Cipher::encrypt(bufferevent *self, bufferevent *partner) {
while (true) {
unsigned char data[1024]{0};
auto data_len = bufferevent_read(partner, data, sizeof(data) - 1);
if (data_len <= 0) {
break;
}
unsigned char temp_data[1024]{0};
for (auto i = 0; i < data_len; i++) {
temp_data[i] = Cipher::password[data[i]];
}
bufferevent_write(self, temp_data, data_len);
}
}

void Cipher::encrypt_byte(unsigned char bytes[], int len) {
auto t_bytes = new unsigned char(len);
for (int k = 0; k < len; k++) {
t_bytes[k] = bytes[k];
}
for (int i = 0; i < len; ++i) {
bytes[i] = Cipher::password[t_bytes[i]];
}
delete t_bytes;
}

void Cipher::decrypt_bytes(unsigned char bytes[], int len) {
unsigned char r_password[256] = {0};
auto t_bytes = new unsigned char(len);
for (int k = 0; k < len; k++) {
t_bytes[k] = bytes[k];
}
for (auto j = 0; j < 256; j++) {
r_password[Cipher::password[j]] = j;
}
for (int i = 0; i < len; i++) {
bytes[i] = r_password[t_bytes[i]];
}
delete t_bytes;
}

unsigned char Cipher::password[256]{0};

32 changes: 32 additions & 0 deletions cipher.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// Created by Li on 2020/4/9.
//

#ifndef LIGHTSOCKS_CIPHER_H
#define LIGHTSOCKS_CIPHER_H

#include <string>
#include <event2/buffer.h>
#include <event2/bufferevent.h>

class Cipher {
public:
Cipher() = default;

public:
// TODO bug fixed
static void encrypt_byte(unsigned char bytes[], int len);

static void decrypt_bytes(unsigned char bytes[], int len);

// TODO bug fixed
static void decrypt(bufferevent *self, bufferevent *partner);

static void encrypt(bufferevent *self, bufferevent *partner);

public:
static unsigned char password[256];
};


#endif //LIGHTSOCKS_CIPHER_H
25 changes: 12 additions & 13 deletions client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ void client::remote_read_cb(bufferevent *bev, void *arg) {
dst = bufferevent_get_output(partner);
// remote->dst(remote->remote) 相当于把远程流量转发到本地
evbuffer_add_buffer(dst, temp);
free(temp);
evbuffer_free(temp);
}

void client::close_on_finished_write_cb(struct bufferevent *bev, void *ctx) {
Expand All @@ -196,28 +196,28 @@ void client::listen_cb(evconnlistener *ev, evutil_socket_t s, sockaddr *sin, int
//监听本地客户端,用本地客户端连接的socket
auto bufev_local = bufferevent_socket_new(base, s, BEV_OPT_CLOSE_ON_FREE);
//本地客户端超时为10s
timeval local_time_out = {10, 0};
timeval local_time_out = {0, 0};
bufferevent_set_timeouts(bufev_local, &local_time_out, 0);
//----------------------------------------------------------------------//

//连接到远程客户端
auto bufev_remote = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);

sockaddr_in sin_;
memset(&sin, 0, sizeof(sin));
sin_.sin_family = AF_INET;
sin_.sin_port = htons(remote_port);
evutil_inet_pton(AF_INET, ip, &sin_.sin_addr.s_addr);
sockaddr_in sin_remote{};
memset(&sin_remote, 0, sizeof(sin_remote));
sin_remote.sin_family = AF_INET;
sin_remote.sin_port = htons(remote_port);
evutil_inet_pton(AF_INET, ip, &sin_remote.sin_addr.s_addr);

//远程服务器超时时间为10s
timeval t1 = {15, 0};
timeval t1 = {0, 0};
bufferevent_set_timeouts(bufev_remote, &t1, 0); //读取 写入

//连接服务端
auto re = bufferevent_socket_connect(
bufev_remote,
(sockaddr *) &sin_,
sizeof(sin_));
(sockaddr *) &sin_remote,
sizeof(sin_remote));
if (re == 0) {
spdlog::debug("connect事件完成");
}
Expand Down Expand Up @@ -259,8 +259,7 @@ void client::init() {
}
#else
// 无视管道信号,发送数据给已关闭的socket
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
{
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
// return 1;
}
#endif // _WIN32
Expand All @@ -269,7 +268,7 @@ void client::init() {
base_loop = base;
}
//绑定地址
sockaddr_in sin_local;
sockaddr_in sin_local{};
memset(&sin_local, 0, sizeof(sin_local));
sin_local.sin_family = AF_INET;
sin_local.sin_port = htons(local_port);
Expand Down
17 changes: 16 additions & 1 deletion main_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
#include "spdlog/spdlog.h"
#include <fstream>

#ifdef _WIN32
#include <Windows.h>
#include <tchar.h>
#endif
using ArduinoJson::DynamicJsonDocument;

int main(int argc, char const *argv[]) {
Expand All @@ -12,7 +16,7 @@ int main(int argc, char const *argv[]) {
const char *config_name = "config.json";
DynamicJsonDocument doc{1024};
auto ret = Util::readJsonConfig(config_name, doc);
if (ret) {
if (!ret) {
spdlog::warn("加载配置文件[{}]失败", config_name);
doc.clear();
std::ofstream outfile;
Expand All @@ -38,6 +42,17 @@ int main(int argc, char const *argv[]) {
spdlog::info("读取到远程端口:{}", remote_port);
client::setConfig(ip, local_port, remote_port, password);
doc.clear();
#ifdef _WIN32
PROCESS_INFORMATION pi; //进程信息
STARTUPINFO si; //进程启动信息
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(si);
si.wShowWindow = SW_HIDE;
si.dwFlags = STARTF_USESHOWWINDOW;
if(CreateProcess(_T("privoxy.exe"), _tcsdup(TEXT("config.txt")), 0, 0, false, 0, 0, 0, &si, &pi)){
spdlog::info("调用privoxy成功...");
}
#endif
client::init();
client::clear();
return 0;
Expand Down
47 changes: 47 additions & 0 deletions main_server.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "server.h"
#include "spdlog/spdlog.h"
#include "ArduinoJson-v6.15.0.hpp"
#include "util.h"

#ifndef _WIN32

#include <csignal>
#include <fstream>

#endif
using ArduinoJson::DynamicJsonDocument;
using ArduinoJson::serializeJson;

int main(int argc, char **argv) {
#ifndef _WIN32
if (std::signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
spdlog::warn("管道信号发生...");
}
#endif
spdlog::set_level(spdlog::level::info);

const char *config_name = "config_server.json";
DynamicJsonDocument doc{1024};
auto ret = Util::readJsonConfig(config_name, doc);
if (!ret) {
spdlog::warn("加载配置文件[{}]失败", config_name);
std::ofstream outfile;
doc["listen_port"]=7009;
doc["password"]=Util::genPassword();
outfile.open("config_server.json");
serializeJson(doc,outfile);
outfile.close();
doc.clear();
spdlog::info("已在当前文件夹下自动生成了[config_server.json]", config_name);
}
//read config from json
spdlog::info("成功加载配置文件[{}]", config_name);
const int listen_port = doc["listen_port"];
const char *password = doc["password"];
spdlog::info("读取到监听地址:[::]:{}", listen_port);
spdlog::info("读取到密码:{}", password);

server::setConfig(listen_port, password);
server::run();
server::clear();
}
Loading

0 comments on commit ba426a1

Please sign in to comment.