mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-11-02 16:03:45 +00:00
Obfsproxy standalone mode (#1156)
* ss-libev: Introduce mode parameter for start_plugin Since obfsproxy handles client and server in different ways, no matter standalone or manged mode, so introduce the mode for start_plugin() to support obfsproxy. With more comments added to plugin.h for later developers. Signed-off-by: Adam Anonymous <anonymous_temp_mail@yahoo.co.jp> * ss-libev: Move SS protocol plugin initialization code to start_ss_plugin Move SS protocol plugin initialization to start_ss_plugin() function, as the support for obfsproxy will not use that environment. Also, remove the use of get_current_dir_name() which is a glibc extension, such macro hack will just make code less readable. Not to mention it already screw up code folding of vim. Signed-off-by: Adam Anonymous <anonymous_temp_mail@yahoo.co.jp> * ss-libev: Introduce obfsproxy standalone mode support as plugin Now shadowsocks-libev supports to use obfsproxy as plugin. Currently we only support to use standalone(proxy) mode of obfsproxy, as managed mode needs to use SOCKS5 as upstream forward, while ss-libev doesn't support it yet. And the output from plugin is just trashed for now. Support to pipe them into stdout/stderr will be added later. Signed-off-by: Adam Anonymous <anonymous_temp_mail@yahoo.co.jp> * ss-libev: doc: Fix wrong cmdline parameter for plugin options Command line option for plugin options is "--plugin-opts", not the json option "--plugin_opts" Fix it. Signed-off-by: Adam Anonymous <anonymous_temp_mail@yahoo.co.jp>
This commit is contained in:
committed by
Max Lv
parent
1fc17aca38
commit
98c51cd0d5
@@ -14,7 +14,7 @@ SYNOPSIS
|
||||
[-t <timeout>] [-c <config_file>] [-i <interface>]
|
||||
[-a <user_name>] [-b <local_address] [-n <nofile>]
|
||||
[--fast-open] [--acl <acl_config>] [--mtu <MTU>]
|
||||
[--plugin <plugin_name>] [--plugin_opts <plugin_options]
|
||||
[--plugin <plugin_name>] [--plugin-opts <plugin_options]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -119,7 +119,7 @@ Only available with MPTCP enabled Linux kernel.
|
||||
--plugin <plugin_name>::
|
||||
Enable SIP003 plugin. (Experimental)
|
||||
|
||||
--plugin_opts <plugin_options>::
|
||||
--plugin-opts <plugin_options>::
|
||||
Set SIP003 plugin options. (Experimental)
|
||||
|
||||
-v::
|
||||
|
||||
@@ -15,7 +15,7 @@ SYNOPSIS
|
||||
[-b <local_addr>] [-a <user_name>]
|
||||
[--manager-address <path_to_unix_domain>]
|
||||
[--executable <path_to_server_executable>]
|
||||
[--plugin <plugin_name>] [--plugin_opts <plugin_options>]
|
||||
[--plugin <plugin_name>] [--plugin-opts <plugin_options>]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -109,7 +109,7 @@ Only available in manager mode.
|
||||
--plugin <plugin_name>::
|
||||
Enable SIP003 plugin. (Experimental)
|
||||
|
||||
--plugin_opts <plugin_options>::
|
||||
--plugin-opts <plugin_options>::
|
||||
Set SIP003 plugin options. (Experimental)
|
||||
|
||||
-v::
|
||||
|
||||
@@ -13,7 +13,7 @@ SYNOPSIS
|
||||
[-k <password>] [-m <encrypt_method>] [-f <pid_file>]
|
||||
[-t <timeout>] [-c <config_file>] [-b <local_address>]
|
||||
[-a <user_name>] [-n <nofile>] [--mtu <MTU>]
|
||||
[--plugin <plugin_name>] [--plugin_opts <plugin_options]
|
||||
[--plugin <plugin_name>] [--plugin-opts <plugin_options]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -105,7 +105,7 @@ Only available with MPTCP enabled Linux kernel.
|
||||
--plugin <plugin_name>::
|
||||
Enable SIP003 plugin. (Experimental)
|
||||
|
||||
--plugin_opts <plugin_options>::
|
||||
--plugin-opts <plugin_options>::
|
||||
Set SIP003 plugin options. (Experimental)
|
||||
|
||||
-v::
|
||||
|
||||
@@ -16,7 +16,7 @@ SYNOPSIS
|
||||
[-b <local_address] [--fast-open] [--mptcp]
|
||||
[--acl <acl_config>] [--mtu <MTU>]
|
||||
[--manager-address <path_to_unix_domain>]
|
||||
[--plugin <plugin_name>] [--plugin_opts <plugin_options]
|
||||
[--plugin <plugin_name>] [--plugin-opts <plugin_options]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -126,7 +126,7 @@ Only available with MPTCP enabled Linux kernel.
|
||||
--plugin <plugin_name>::
|
||||
Enable SIP003 plugin. (Experimental)
|
||||
|
||||
--plugin_opts <plugin_options>::
|
||||
--plugin-opts <plugin_options>::
|
||||
Set SIP003 plugin options. (Experimental)
|
||||
|
||||
-v::
|
||||
|
||||
@@ -14,7 +14,7 @@ SYNOPSIS
|
||||
[-t <timeout>] [-c <config_file>] [-i <interface>]
|
||||
[-b <local_addr>] [-a <user_name>] [-n <nofile>]
|
||||
[-L addr:port] [--mtu <MTU>]
|
||||
[--plugin <plugin_name>] [--plugin_opts <plugin_options]
|
||||
[--plugin <plugin_name>] [--plugin-opts <plugin_options]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -116,7 +116,7 @@ Only available with MPTCP enabled Linux kernel.
|
||||
--plugin <plugin_name>::
|
||||
Enable SIP003 plugin. (Experimental)
|
||||
|
||||
--plugin_opts <plugin_options>::
|
||||
--plugin-opts <plugin_options>::
|
||||
Set SIP003 plugin options. (Experimental)
|
||||
|
||||
-v::
|
||||
|
||||
+1
-1
@@ -1453,7 +1453,7 @@ main(int argc, char **argv)
|
||||
len = strlen(remote_str);
|
||||
}
|
||||
int err = start_plugin(plugin, plugin_opts, remote_str,
|
||||
remote_port, plugin_host, plugin_port);
|
||||
remote_port, plugin_host, plugin_port, MODE_CLIENT);
|
||||
if (err) {
|
||||
FATAL("failed to start the plugin");
|
||||
}
|
||||
|
||||
+143
-35
@@ -78,51 +78,23 @@ struct cork_stream_consumer plugin_log = {
|
||||
.free = plugin_log__free,
|
||||
};
|
||||
|
||||
int
|
||||
start_plugin(const char *plugin,
|
||||
const char *plugin_opts,
|
||||
const char *remote_host,
|
||||
const char *remote_port,
|
||||
const char *local_host,
|
||||
const char *local_port)
|
||||
static int start_ss_plugin(const char *plugin,
|
||||
const char *plugin_opts,
|
||||
const char *remote_host,
|
||||
const char *remote_port,
|
||||
const char *local_host,
|
||||
const char *local_port,
|
||||
enum plugin_mode mode)
|
||||
{
|
||||
char *new_path = NULL;
|
||||
char *cmd = NULL;
|
||||
|
||||
if (plugin == NULL)
|
||||
return -1;
|
||||
|
||||
if (strlen(plugin) == 0)
|
||||
return 0;
|
||||
|
||||
size_t plugin_len = strlen(plugin);
|
||||
size_t cmd_len = plugin_len + CMD_RESRV_LEN;
|
||||
cmd = ss_malloc(cmd_len);
|
||||
|
||||
snprintf(cmd, cmd_len, "exec %s", plugin);
|
||||
|
||||
env = cork_env_clone_current();
|
||||
const char *path = cork_env_get(env, "PATH");
|
||||
if (path != NULL) {
|
||||
#ifdef __GLIBC__
|
||||
char *cwd = get_current_dir_name();
|
||||
if (cwd) {
|
||||
#else
|
||||
char cwd[PATH_MAX];
|
||||
if (!getcwd(cwd, PATH_MAX)) {
|
||||
#endif
|
||||
size_t path_len = strlen(path) + strlen(cwd) + 2;
|
||||
new_path = ss_malloc(path_len);
|
||||
snprintf(new_path, path_len, "%s:%s", cwd, path);
|
||||
#ifdef __GLIBC__
|
||||
free(cwd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (new_path != NULL)
|
||||
cork_env_add(env, "PATH", new_path);
|
||||
|
||||
cork_env_add(env, "SS_REMOTE_HOST", remote_host);
|
||||
cork_env_add(env, "SS_REMOTE_PORT", remote_port);
|
||||
|
||||
@@ -148,6 +120,142 @@ start_plugin(const char *plugin,
|
||||
return err;
|
||||
}
|
||||
|
||||
#define OBFSPROXY_OPTS_MAX 4096
|
||||
/*
|
||||
* For obfsproxy, we use standalone mode for now.
|
||||
* Managed mode needs to use SOCKS5 proxy as forwarder, which is not supported
|
||||
* yet.
|
||||
*
|
||||
* The idea of using standalone mode is quite simple, just assemble the
|
||||
* internal port into obfsproxy parameters.
|
||||
*
|
||||
* Using manually ran scramblesuit as an example:
|
||||
* obfsproxy \
|
||||
* --data-dir /tmp/ss_libev_plugin_with_suffix \
|
||||
* scramblesuit \
|
||||
* --password SOMEMEANINGLESSPASSWORDASEXAMPLE \
|
||||
* --dest some.server.org:12345 \
|
||||
* client \
|
||||
* 127.0.0.1:54321
|
||||
*
|
||||
* In above case, @plugin = "obfsproxy",
|
||||
* @plugin_opts = "scramblesuit --password SOMEMEANINGLESSPASSWORDASEXAMPLE"
|
||||
* For obfs3, it's even easier, just pass @plugin = "obfsproxy"
|
||||
* @plugin_opts = "obfs3"
|
||||
*
|
||||
* And the rest parameters are all assembled here.
|
||||
* Some old obfsproxy will not be supported as it doesn't even support
|
||||
* "--data-dir" option
|
||||
*/
|
||||
static int start_obfsproxy(const char *plugin,
|
||||
const char *plugin_opts,
|
||||
const char *remote_host,
|
||||
const char *remote_port,
|
||||
const char *local_host,
|
||||
const char *local_port,
|
||||
enum plugin_mode mode)
|
||||
{
|
||||
char *pch;
|
||||
char *opts_dump;
|
||||
char buf[PATH_MAX];
|
||||
int ret;
|
||||
|
||||
opts_dump = strndup(plugin_opts, OBFSPROXY_OPTS_MAX);
|
||||
if (!opts_dump) {
|
||||
ERROR("start_obfsproxy strndup failed");
|
||||
return -ENOMEM;
|
||||
}
|
||||
exec = cork_exec_new(plugin);
|
||||
|
||||
/* The first parameter will be skipped, so pass @plugin again */
|
||||
cork_exec_add_param(exec, plugin);
|
||||
|
||||
cork_exec_add_param(exec, "--data-dir");
|
||||
snprintf(buf, PATH_MAX, "/tmp/%s_%s:%s_%s:%s", plugin,
|
||||
remote_host, remote_port, local_host, local_port);
|
||||
cork_exec_add_param(exec, buf);
|
||||
|
||||
/*
|
||||
* Iterate @plugin_opts by space
|
||||
*/
|
||||
pch = strtok(opts_dump, " ");
|
||||
while (pch) {
|
||||
cork_exec_add_param(exec, pch);
|
||||
pch = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
/* The rest options */
|
||||
if (mode == MODE_CLIENT) {
|
||||
/* Client mode */
|
||||
cork_exec_add_param(exec, "--dest");
|
||||
snprintf(buf, PATH_MAX, "%s:%s", remote_host, remote_port);
|
||||
cork_exec_add_param(exec, buf);
|
||||
cork_exec_add_param(exec, "client");
|
||||
snprintf(buf, PATH_MAX, "%s:%s", local_host, local_port);
|
||||
cork_exec_add_param(exec, buf);
|
||||
} else {
|
||||
/* Server mode */
|
||||
cork_exec_add_param(exec, "--dest");
|
||||
snprintf(buf, PATH_MAX, "%s:%s", local_host, local_port);
|
||||
cork_exec_add_param(exec, buf);
|
||||
cork_exec_add_param(exec, "server");
|
||||
snprintf(buf, PATH_MAX, "%s:%s", remote_host, remote_port);
|
||||
cork_exec_add_param(exec, buf);
|
||||
}
|
||||
cork_exec_set_env(exec, env);
|
||||
sub = cork_subprocess_new_exec(exec, NULL, NULL, &exit_code);
|
||||
ret = cork_subprocess_start(sub);
|
||||
ss_free(opts_dump);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
start_plugin(const char *plugin,
|
||||
const char *plugin_opts,
|
||||
const char *remote_host,
|
||||
const char *remote_port,
|
||||
const char *local_host,
|
||||
const char *local_port,
|
||||
enum plugin_mode mode)
|
||||
{
|
||||
char *new_path = NULL;
|
||||
const char *current_path;
|
||||
char cwd[PATH_MAX];
|
||||
size_t new_path_len;
|
||||
int ret;
|
||||
|
||||
if (plugin == NULL)
|
||||
return -1;
|
||||
|
||||
if (strlen(plugin) == 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Add current dir to PATH, so we can search plugin in current dir
|
||||
*/
|
||||
env = cork_env_clone_current();
|
||||
current_path = cork_env_get(env, "PATH");
|
||||
if (current_path != NULL) {
|
||||
if (!getcwd(cwd, PATH_MAX)) {
|
||||
new_path_len = strlen(current_path) + strlen(cwd) + 2;
|
||||
new_path = ss_malloc(new_path_len);
|
||||
snprintf(new_path, new_path_len, "%s:%s", cwd, current_path);
|
||||
}
|
||||
}
|
||||
if (new_path != NULL)
|
||||
cork_env_add(env, "PATH", new_path);
|
||||
|
||||
if (!strncmp(plugin, "obfsproxy", strlen("obfsproxy")))
|
||||
ret = start_obfsproxy(plugin, plugin_opts, remote_host, remote_port,
|
||||
local_host, local_port, mode);
|
||||
else
|
||||
ret = start_ss_plugin(plugin, plugin_opts, remote_host, remote_port,
|
||||
local_host, local_port, mode);
|
||||
ss_free(new_path);
|
||||
env = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
get_local_port()
|
||||
{
|
||||
|
||||
+38
-1
@@ -27,12 +27,49 @@
|
||||
#define PLUGIN_EXIT_NORMAL -1
|
||||
#define PLUGIN_RUNNING 0
|
||||
|
||||
enum plugin_mode {
|
||||
MODE_CLIENT,
|
||||
MODE_SERVER
|
||||
};
|
||||
|
||||
/*
|
||||
* XXX: Since we have SS plugins and obfsproxy support, for now we will
|
||||
* do extra check against the plugin name.
|
||||
* For obfsproxy, we will not follow the SS specified protocol and
|
||||
* do special routine for obfsproxy.
|
||||
* This may change when the protocol is finally settled
|
||||
*
|
||||
* Main function to start a plugin.
|
||||
*
|
||||
* @plugin: name of the plugin
|
||||
* search from PATH and current directory.
|
||||
* @plugin_opts: Special options for plugin
|
||||
* @remote_host:
|
||||
* CLIENT mode:
|
||||
* The remote server address, which also runs corresponding plugin
|
||||
* SERVER mode:
|
||||
* The real listen address, which plugin will listen to
|
||||
* @remote_port:
|
||||
* CLIENT mode:
|
||||
* The remote server port, which corresponding plugin is listening to
|
||||
* SERVER mode:
|
||||
* The real listen port, which plugin will listen to
|
||||
* @local_host:
|
||||
* Where ss-libev will connect/listen to.
|
||||
* Normally localhost for both modes.
|
||||
* @local_port:
|
||||
* Where ss-libev will connect/listen to.
|
||||
* Internal user port.
|
||||
* @mode:
|
||||
* Indicates which mode the plugin should run at.
|
||||
*/
|
||||
int start_plugin(const char *plugin,
|
||||
const char *plugin_opts,
|
||||
const char *remote_host,
|
||||
const char *remote_port,
|
||||
const char *local_host,
|
||||
const char *local_port);
|
||||
const char *local_port,
|
||||
enum plugin_mode mode);
|
||||
uint16_t get_local_port();
|
||||
void stop_plugin();
|
||||
int is_plugin_running();
|
||||
|
||||
+1
-1
@@ -1028,7 +1028,7 @@ main(int argc, char **argv)
|
||||
len = strlen(remote_str);
|
||||
}
|
||||
int err = start_plugin(plugin, plugin_opts, remote_str,
|
||||
remote_port, plugin_host, plugin_port);
|
||||
remote_port, plugin_host, plugin_port, MODE_CLIENT);
|
||||
if (err) {
|
||||
FATAL("failed to start the plugin");
|
||||
}
|
||||
|
||||
+1
-1
@@ -1884,7 +1884,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
int err = start_plugin(plugin, plugin_opts, server_str,
|
||||
plugin_port, "127.0.0.1", server_port);
|
||||
plugin_port, "127.0.0.1", server_port, MODE_SERVER);
|
||||
if (err) {
|
||||
FATAL("failed to start the plugin");
|
||||
}
|
||||
|
||||
+1
-1
@@ -1011,7 +1011,7 @@ main(int argc, char **argv)
|
||||
len = strlen(remote_str);
|
||||
}
|
||||
int err = start_plugin(plugin, plugin_opts, remote_str,
|
||||
remote_port, plugin_host, plugin_port);
|
||||
remote_port, plugin_host, plugin_port, MODE_CLIENT);
|
||||
if (err) {
|
||||
FATAL("failed to start the plugin");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user