diff --git a/README.md b/README.md index f286c80..45ffd42 100755 --- a/README.md +++ b/README.md @@ -64,6 +64,36 @@ 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 +# 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 +--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 +121,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/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/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/doc/README.zh-cn.md b/doc/README.zh-cn.md index 41ffca1..8a39542 100644 --- a/doc/README.zh-cn.md +++ b/doc/README.zh-cn.md @@ -80,6 +80,34 @@ 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) diff --git a/main.cpp b/main.cpp index bbc30ec..45e5c42 100755 --- a/main.cpp +++ b/main.cpp @@ -3,6 +3,11 @@ #include "log.h" #include "lib/md5.h" #include "encrypt.h" +#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; @@ -2517,6 +2522,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,7 +2546,68 @@ void print_help() //printf("common options,these options must be same on both side\n"); } -void process_arg(int argc, char *argv[]) +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; +} +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. + // See config.example for example configurations + std::ifstream conf_file(config_file); + std::string line; + std::vector arguments; + while(std::getline(conf_file,line)) + { + line = trim_config_line(line); + if(line==""||line.at(0)=='#') + { + continue; + } + auto pos = find_config_divider(line); + 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(trim_config_line(p1)); + arguments.push_back(trim_config_line(p2)); + } + } + conf_file.close(); + + // 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) @@ -2578,6 +2652,39 @@ void process_arg(int argc, char *argv[]) print_help(); myexit(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) { @@ -2839,6 +2946,10 @@ void process_arg(int argc, char *argv[]) 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);