From 968d35178a3e170fd15be3146e44a3a0e4109b8b Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Mon, 21 Aug 2017 14:47:06 +0800 Subject: [PATCH 1/9] main: allow loading configuration files (--config-file) --- config.example | 16 +++++++++++++++ main.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 config.example diff --git a/config.example b/config.example new file mode 100644 index 0000000..470ea1d --- /dev/null +++ b/config.example @@ -0,0 +1,16 @@ +# Basically this file is the equivalent to splitting the command line options into multiple lines +# Each line should contain an option + +# This is client +-c +# Or use -s if you use it on server side +# Define local address +-l 127.0.0.1:56789 +# Define remote address +-r 45.66.77.88:45678 +# Password +-k my_awesome_password +# Mode +--raw-mode faketcp +# Log Level +--log-level 4 diff --git a/main.cpp b/main.cpp index bbc30ec..942a484 100755 --- a/main.cpp +++ b/main.cpp @@ -3,6 +3,9 @@ #include "log.h" #include "lib/md5.h" #include "encrypt.h" +#include +#include +#include char local_ip[100]="0.0.0.0", remote_ip[100]="255.255.255.255",source_ip[100]="0.0.0.0"; u32_t local_ip_uint32,remote_ip_uint32,source_ip_uint32; @@ -2517,6 +2520,7 @@ void print_help() printf(" this option disables port changing while re-connecting\n"); // printf(" \n"); printf("other options:\n"); + printf(" --config-file read options from a configuration file instead of command line\n"); printf(" --log-level 0:never 1:fatal 2:error 3:warn \n"); printf(" 4:info (default) 5:debug 6:trace\n"); // printf("\n"); @@ -2540,6 +2544,43 @@ void print_help() //printf("common options,these options must be same on both side\n"); } +void process_arg(int argc, char *argv[]); +void load_config(char *config_file, char *argv0) +{ + // Load configurations from config_file instead of the command line. + // See config.example for example configurations + std::ifstream conf_file(config_file); + std::string line; + std::vector arguments; + while(std::getline(conf_file,line)) + { + if(line.at(0)=='#') + { + continue; + } + auto pos = line.find(" ",0); + if(pos==std::string::npos) + { + arguments.push_back(line); + } + else + { + auto p1 = line.substr(0,pos); + auto p2 = line.substr(pos+1,line.length() - pos - 1); + arguments.push_back(p1); + arguments.push_back(p2); + } + } + conf_file.close(); + int argc = arguments.size(); + char *argv[argc+1]; + argv[0]=argv0; + for(int i=0; i Date: Mon, 21 Aug 2017 15:00:27 +0800 Subject: [PATCH 2/9] README: document configuration files --- README.md | 26 ++++++++++++++++++++++++++ doc/README.zh-cn.md | 25 +++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/README.md b/README.md index f286c80..fc63cb3 100755 --- a/README.md +++ b/README.md @@ -64,6 +64,31 @@ Assume your UDP is blocked or being QOS-ed or just poorly supported. Assume your Now,an encrypted raw tunnel has been established between client and server through TCP port 4096. Connecting to UDP port 3333 at the client side is equivalent to connecting to port 7777 at the server side. No UDP traffic will be exposed. +### Configuration files + +Alternatively, you can store the options into a configuration file in order to keep the secrets away from command line arguments. + +For example, rewrite the options for the above `server` example into configuration file: + +`server.conf` + +``` +-s +-l 0.0.0.0:4096 +-r 127.0.0.1:7777 +-a +-k passwd +--raw-mode faketcp +``` + +Pay attention to the `-k` parameter: the quotes around the password are removed. In configuration files we do not need quotes. + +Then you could start the server with + +```bash +./udp2raw_amd64 --config-file server.conf +``` + ### Note to run on Android, see [Android_Guide](/doc/android_guide.md) @@ -91,6 +116,7 @@ client options: --source-port force source-port for raw socket,tcp/udp only this option disables port changing while re-connecting other options: + --config-file read options from a configuration file instead of command line --log-level 0:never 1:fatal 2:error 3:warn 4:info (default) 5:debug 6:trace --log-position enable file name,function name,line number in log diff --git a/doc/README.zh-cn.md b/doc/README.zh-cn.md index 41ffca1..1423c6e 100644 --- a/doc/README.zh-cn.md +++ b/doc/README.zh-cn.md @@ -80,6 +80,31 @@ https://github.com/wangyu-/udp2raw-tunnel/releases 现在client和server之间建立起了,tunnel。想要在本地连接44.55.66.77:7777,只需要连接 127.0.0.1:3333。来回的所有的udp流量会被经过tunneling发送。在外界看起来是tcp流量,不会有udp流量暴露到公网。 +### 配置文件 + +为了避免将密码等私密信息暴露在进程命令行参数内,你也可以使用 `配置文件` 来存储参数。 + +比如,将以上服务端参数改写成配置文件 + +`server.conf`: + +``` +-s +-l 0.0.0.0:4096 +-r 127.0.0.1:7777 +-a +-k passwd +--raw-mode faketcp +``` + +注意,当写入配置文件的时候,密码等参数两边的引号必须去除。 + +然后就可以使用下面的方式启动服务端 + +```bash +./udp2raw_amd64 --config-file server.conf +``` + ### 提醒 如果要在anroid上运行,请看[Android简明教程](/doc/android_guide.md) From ab0ce3ade34ec397ad2ad2123c0debf455d06534 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Mon, 21 Aug 2017 20:41:22 +0800 Subject: [PATCH 3/9] main: merge cli/config arguments and check for duplications --- main.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/main.cpp b/main.cpp index 942a484..0501d30 100755 --- a/main.cpp +++ b/main.cpp @@ -2544,8 +2544,8 @@ void print_help() //printf("common options,these options must be same on both side\n"); } -void process_arg(int argc, char *argv[]); -void load_config(char *config_file, char *argv0) +void process_arg(int argc, char *argv[], bool read_config = true); +void load_config(char *config_file, int argc_orig, char *argv_orig[]) { // Load configurations from config_file instead of the command line. // See config.example for example configurations @@ -2572,16 +2572,24 @@ void load_config(char *config_file, char *argv0) } } conf_file.close(); - int argc = arguments.size(); - char *argv[argc+1]; - argv[0]=argv0; + + // Append the new arguments to the original argv + int argc = arguments.size() + argc_orig; + char *argv[argc]; for(int i=0; i short_opts_map = { + {"-k","--key"}, + {"-a","--auto-rule"}, + {"-g","--gen-rule"}, + }; // Keep this in sync with the shortcuts - int option_index = 0; + int option_index = 0; + std::set checked_opts = {}; for (i = 0; i < argc; i++) { if(strcmp(argv[i],"-h")==0||strcmp(argv[i],"--help")==0) @@ -2621,11 +2635,11 @@ void process_arg(int argc, char *argv[]) myexit(0); } - if(strcmp(argv[i],"--config-file")==0) + if(read_config&&strcmp(argv[i],"--config-file")==0) { if(isecond; + } + if(checked_opts.find(opt)!=checked_opts.end()) + { + char *err_msg = new char(255); + sprintf(err_msg,"Duplicate argument %s",opt.c_str()); + log_bare(log_fatal,err_msg); + myexit(-1); + } + checked_opts.insert(opt); + } } if (argc == 1) { From 57b874ee6d84eaec57db88d0503f940a34a5ea36 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Mon, 21 Aug 2017 20:42:51 +0800 Subject: [PATCH 4/9] main: ignore empty lines in configuration --- main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index 0501d30..b3c043e 100755 --- a/main.cpp +++ b/main.cpp @@ -2554,7 +2554,7 @@ void load_config(char *config_file, int argc_orig, char *argv_orig[]) std::vector arguments; while(std::getline(conf_file,line)) { - if(line.at(0)=='#') + if(line==""||line.at(0)=='#') { continue; } From 6ef38709a669772f0e3724633d2267aac629ea1b Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Wed, 23 Aug 2017 10:38:55 +0800 Subject: [PATCH 5/9] config: trim spaces and tabs --- common.cpp | 11 +++++++++++ common.h | 2 ++ main.cpp | 11 +++++++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/common.cpp b/common.cpp index 1bfc6fd..2088e34 100644 --- a/common.cpp +++ b/common.cpp @@ -607,3 +607,14 @@ int run_command_no_log(string command0,char * &output) { return 0; }*/ + +// Remove preceding and trailing characters +string trim(const string& str, char c) { + size_t first = str.find_first_not_of(c); + if(string::npos==first) + { + return ""; + } + size_t last = str.find_last_not_of(c); + return str.substr(first,(last-first+1)); +} diff --git a/common.h b/common.h index 33562d0..5504af1 100644 --- a/common.h +++ b/common.h @@ -164,6 +164,8 @@ int read_file(const char * file,char * &output); vector string_to_vec(const char * s,const char * sp); vector< vector > string_to_vec2(const char * s); +string trim(const string& str, char c); + //extern string iptables_pattern; #endif /* COMMON_H_ */ diff --git a/main.cpp b/main.cpp index b3c043e..6e9166d 100755 --- a/main.cpp +++ b/main.cpp @@ -2545,6 +2545,12 @@ void print_help() //printf("common options,these options must be same on both side\n"); } void process_arg(int argc, char *argv[], bool read_config = true); +std::string trim_config_line(std::string line) +{ + auto str = trim(line, ' '); // Space + str = trim(str, ' '); // Tab + return str; +} void load_config(char *config_file, int argc_orig, char *argv_orig[]) { // Load configurations from config_file instead of the command line. @@ -2554,6 +2560,7 @@ void load_config(char *config_file, int argc_orig, char *argv_orig[]) std::vector arguments; while(std::getline(conf_file,line)) { + line = trim_config_line(line); if(line==""||line.at(0)=='#') { continue; @@ -2567,8 +2574,8 @@ void load_config(char *config_file, int argc_orig, char *argv_orig[]) { auto p1 = line.substr(0,pos); auto p2 = line.substr(pos+1,line.length() - pos - 1); - arguments.push_back(p1); - arguments.push_back(p2); + arguments.push_back(trim_config_line(p1)); + arguments.push_back(trim_config_line(p2)); } } conf_file.close(); From 01e0e51b9b4fc543ff6bb5c8e9190c017365f86d Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Wed, 23 Aug 2017 10:57:29 +0800 Subject: [PATCH 6/9] config: treat TABs as spaces --- main.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/main.cpp b/main.cpp index 6e9166d..8689152 100755 --- a/main.cpp +++ b/main.cpp @@ -2551,6 +2551,15 @@ std::string trim_config_line(std::string line) str = trim(str, ' '); // Tab return str; } +std::size_t find_config_divider(std::string line) +{ + std::size_t pos = line.find(" ",0); // Space + if(pos==std::string::npos) + { + pos = line.find(" ",0); // Tab + } + return pos; +} void load_config(char *config_file, int argc_orig, char *argv_orig[]) { // Load configurations from config_file instead of the command line. @@ -2565,7 +2574,7 @@ void load_config(char *config_file, int argc_orig, char *argv_orig[]) { continue; } - auto pos = line.find(" ",0); + auto pos = find_config_divider(line); if(pos==std::string::npos) { arguments.push_back(line); From 1f2f0d96fd60b02da9f66a475620dad53cca3aff Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Wed, 23 Aug 2017 11:09:46 +0800 Subject: [PATCH 7/9] main: fix missing includes --- main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/main.cpp b/main.cpp index 8689152..38f0c7f 100755 --- a/main.cpp +++ b/main.cpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include char local_ip[100]="0.0.0.0", remote_ip[100]="255.255.255.255",source_ip[100]="0.0.0.0"; u32_t local_ip_uint32,remote_ip_uint32,source_ip_uint32; From 057f81007d9e9bc6e16ed59c0464375d56b30d4c Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Wed, 23 Aug 2017 11:16:41 +0800 Subject: [PATCH 8/9] main: don't warn config-file as 'unknown' --- main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/main.cpp b/main.cpp index 38f0c7f..45e5c42 100755 --- a/main.cpp +++ b/main.cpp @@ -2946,6 +2946,10 @@ void process_arg(int argc, char *argv[], bool read_config) myexit(-1); } } + else if(strcmp(long_options[option_index].name,"config-file")==0) + { + mylog(log_info,"configuration loaded from %s\n",optarg); + } else { mylog(log_warn,"ignored unknown long option ,option_index:%d code:<%x>\n",option_index, optopt); From 2269879a2e946be08330341854d5d5ec9d295bb3 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Wed, 23 Aug 2017 11:22:33 +0800 Subject: [PATCH 9/9] doc: note about comments --- README.md | 5 +++++ doc/README.zh-cn.md | 3 +++ 2 files changed, 8 insertions(+) diff --git a/README.md b/README.md index fc63cb3..45ffd42 100755 --- a/README.md +++ b/README.md @@ -74,7 +74,12 @@ For example, rewrite the options for the above `server` example into configurati ``` -s +# You can add comments like this +# Comments MUST occupy an entire line +# Or they will not work as expected +# Listen address -l 0.0.0.0:4096 +# Remote address -r 127.0.0.1:7777 -a -k passwd diff --git a/doc/README.zh-cn.md b/doc/README.zh-cn.md index 1423c6e..8a39542 100644 --- a/doc/README.zh-cn.md +++ b/doc/README.zh-cn.md @@ -90,6 +90,9 @@ https://github.com/wangyu-/udp2raw-tunnel/releases ``` -s +# 你可以像这样添加注释 +# 注意,只有整行注释才能在配置文件里使用 +# 注释必须独占一行 -l 0.0.0.0:4096 -r 127.0.0.1:7777 -a