Merge pull request #30 from PeterCxy/patch-config-file

Allow loading options from configuration files
This commit is contained in:
wangyu- 2017-08-22 22:01:28 -07:00 committed by GitHub
commit 020242b73d
6 changed files with 201 additions and 2 deletions

View File

@ -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 <port> force source-port for raw socket,tcp/udp only
this option disables port changing while re-connecting
other options:
--config-file <string> read options from a configuration file instead of command line
--log-level <number> 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

View File

@ -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));
}

View File

@ -164,6 +164,8 @@ int read_file(const char * file,char * &output);
vector<string> string_to_vec(const char * s,const char * sp);
vector< vector <string> > string_to_vec2(const char * s);
string trim(const string& str, char c);
//extern string iptables_pattern;
#endif /* COMMON_H_ */

16
config.example Normal file
View File

@ -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

View File

@ -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)

115
main.cpp
View File

@ -3,6 +3,11 @@
#include "log.h"
#include "lib/md5.h"
#include "encrypt.h"
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <set>
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 <string> read options from a configuration file instead of command line\n");
printf(" --log-level <number> 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<std::string> 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<argc; i++)
{
if(i<argc_orig)
{
argv[i] = argv_orig[i];
}
else
{
argv[i] = (char*)arguments[i-argc_orig].c_str();
}
}
process_arg(argc,argv,false);
}
void process_arg(int argc, char *argv[], bool read_config)
{
int i,j,k,opt;
static struct option long_options[] =
@ -2567,10 +2634,17 @@ void process_arg(int argc, char *argv[])
{"lower-level", required_argument, 0, 1},
{"sock-buf", required_argument, 0, 1},
{"seq-mode", required_argument, 0, 1},
{"config-file", required_argument, 0, 1},
{NULL, 0, 0, 0}
};
static std::map<string,string> 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<string> 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(i<argc-1)
{
load_config(argv[i+1],argc,argv);
return;
}
else
{
log_bare(log_fatal,"you must provide path to the configuration file when using --config-file");
myexit(-1);
}
}
// Check for duplicate arguments
if(strncmp("-",argv[i],1)==0)
{
std::string opt(argv[i]);
auto iter = short_opts_map.find(opt);
if(iter!=short_opts_map.end())
{
opt = iter->second;
}
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);