Browse Source

Merge pull request #45 from madeye/ss-tunnel

Add tunnel mode
pull/51/head
Max Lv 11 years ago
parent
commit
26f46bee1f
18 changed files with 1276 additions and 64 deletions
  1. 63
      Changes
  2. 20
      configure
  3. 2
      configure.ac
  4. 6
      debian/changelog
  5. 27
      src/Makefile.am
  6. 156
      src/Makefile.in
  7. 3
      src/include.h
  8. 15
      src/jconf.c
  9. 10
      src/jconf.h
  10. 5
      src/local.c
  11. 2
      src/local.h
  12. 5
      src/redir.c
  13. 2
      src/redir.h
  14. 884
      src/tunnel.c
  15. 76
      src/tunnel.h
  16. 48
      src/udprelay.c
  17. 3
      src/udprelay.h
  18. 13
      src/utils.c

63
Changes

@ -1,47 +1,74 @@
Changelog
---------
shadowsocks (1.4.3-1) unstable; urgency=low
1.4.2 -- Sun, 05 Jan 2014 10:05:29 +0900
* Add tunnel mode with local port forwarding feature.
-- Max Lv <max.c.lv@gmail.com> Fri, 21 Feb 2014 11:52:13 +0900
shadowsocks (1.4.2-1) unstable; urgency=high
* Fix the UDP relay issues. * Fix the UDP relay issues.
* Add syslog support. * Add syslog support.
1.4.1 -- Tue, 12 Nov 2013 03:57:21 +0000
-- Max Lv <max.c.lv@gmail.com> Sun, 05 Jan 2014 10:05:29 +0900
shadowsocks (1.4.1-1) unstable; urgency=low
* Add multi-port support. * Add multi-port support.
* Add PolarSSL support by @linusyang. * Add PolarSSL support by @linusyang.
1.4.0 -- Sun, 08 Sep 2013 02:20:40 +0000
-- Max Lv <max.c.lv@gmail.com> Tue, 12 Nov 2013 03:57:21 +0000
shadowsocks (1.4.0-1) unstable; urgency=low
* Add standard socks5 udp support. * Add standard socks5 udp support.
1.3.3 -- Fri, 21 Jun 2013 09:59:20 +0800
-- Max Lv <max.c.lv@gmail.com> Sun, 08 Sep 2013 02:20:40 +0000
shadowsocks (1.3.3-1) unstable; urgency=high
* Provide more info in verbose mode. * Provide more info in verbose mode.
1.3.2 -- Sun, 09 Jun 2013 09:52:31 +0000
-- Max Lv <max.c.lv@gmail.com> Fri, 21 Jun 2013 09:59:20 +0800
shadowsocks (1.3.2-1) unstable; urgency=high
* Fix some ciphers by @linusyang. * Fix some ciphers by @linusyang.
1.3.1 -- Tue, 04 Jun 2013 00:56:17 +0000
-- Max Lv <max.c.lv@gmail.com> Sun, 09 Jun 2013 09:52:31 +0000
shadowsocks (1.3.1-1) unstable; urgency=low
* Support more cihpers: camellia, idea, rc2 and seed. * Support more cihpers: camellia, idea, rc2 and seed.
1.3 -- Thu, 16 May 2013 10:51:15 +0800
-- Max Lv <max.c.lv@gmail.com> Tue, 04 Jun 2013 00:56:17 +0000
shadowsocks (1.3-1) unstable; urgency=low
* Able to bind connections to specific interface.
* Support more ciphers: aes-128-cfb, aes-192-cfb, aes-256-cfb, bf-cfb, cast5-cfb, des-cfb.
-- Max Lv <max.c.lv@gmail.com> Thu, 16 May 2013 10:51:15 +0800
shadowsocks (1.2-2) unstable; urgency=low
* Close timeouted TCP connections.
-- Max Lv <max.c.lv@gmail.com> Tue, 07 May 2013 14:10:33 +0800
shadowsocks (1.2-1) unstable; urgency=low
* Able to bind connections to specific interface
* Support more ciphers: aes-128-cfb, aes-192-cfb, aes-256-cfb, bf-cfb, cast5-cfb, des-cfb
* Fix a high load issue.
1.2 -- Tue, 07 May 2013 14:10:33 +0800
-- Max Lv <max.c.lv@gmail.com> Thu, 18 Apr 2013 10:52:34 +0800
* Close timeouted TCP connections
* Fix a high load issue
shadowsocks (1.1-1) unstable; urgency=low
1.1 -- Wed, 10 Apr 2013 12:11:36 +0800
* Fix a IPV6 resolve issue.
* Fix a IPV6 resolve issue
-- Max Lv <max.c.lv@gmail.com> Wed, 10 Apr 2013 12:11:36 +0800
1.0 -- Sat, 06 Apr 2013 16:59:15 +0800
shadowsocks (1.0-2) unstable; urgency=low
* Initial release
* Initial release.
-- Max Lv <max.c.lv@gmail.com> Sat, 06 Apr 2013 16:59:15 +0800

20
configure

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for shadowsocks 1.4.2.
# Generated by GNU Autoconf 2.69 for shadowsocks 1.4.3.
# #
# Report bugs to <max.c.lv@gmail.com>. # Report bugs to <max.c.lv@gmail.com>.
# #
@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='shadowsocks' PACKAGE_NAME='shadowsocks'
PACKAGE_TARNAME='shadowsocks' PACKAGE_TARNAME='shadowsocks'
PACKAGE_VERSION='1.4.2'
PACKAGE_STRING='shadowsocks 1.4.2'
PACKAGE_VERSION='1.4.3'
PACKAGE_STRING='shadowsocks 1.4.3'
PACKAGE_BUGREPORT='max.c.lv@gmail.com' PACKAGE_BUGREPORT='max.c.lv@gmail.com'
PACKAGE_URL='' PACKAGE_URL=''
@ -1324,7 +1324,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures shadowsocks 1.4.2 to adapt to many kinds of systems.
\`configure' configures shadowsocks 1.4.3 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1394,7 +1394,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of shadowsocks 1.4.2:";;
short | recursive ) echo "Configuration of shadowsocks 1.4.3:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1510,7 +1510,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
shadowsocks configure 1.4.2
shadowsocks configure 1.4.3
generated by GNU Autoconf 2.69 generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc. Copyright (C) 2012 Free Software Foundation, Inc.
@ -2033,7 +2033,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by shadowsocks $as_me 1.4.2, which was
It was created by shadowsocks $as_me 1.4.3, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@ $ $0 $@
@ -2853,7 +2853,7 @@ fi
# Define the identity of the package. # Define the identity of the package.
PACKAGE='shadowsocks' PACKAGE='shadowsocks'
VERSION='1.4.2'
VERSION='1.4.3'
cat >>confdefs.h <<_ACEOF cat >>confdefs.h <<_ACEOF
@ -15450,7 +15450,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by shadowsocks $as_me 1.4.2, which was
This file was extended by shadowsocks $as_me 1.4.3, which was
generated by GNU Autoconf 2.69. Invocation command line was generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -15516,7 +15516,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\ ac_cs_version="\\
shadowsocks config.status 1.4.2
shadowsocks config.status 1.4.3
configured by $0, generated by GNU Autoconf 2.69, configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"

2
configure.ac

@ -2,7 +2,7 @@ dnl -*- Autoconf -*-
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
AC_PREREQ([2.67]) AC_PREREQ([2.67])
AC_INIT([shadowsocks], [1.4.2], [max.c.lv@gmail.com])
AC_INIT([shadowsocks], [1.4.3], [max.c.lv@gmail.com])
AC_CONFIG_SRCDIR([src/encrypt.c]) AC_CONFIG_SRCDIR([src/encrypt.c])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])

6
debian/changelog

@ -1,3 +1,9 @@
shadowsocks (1.4.3-1) unstable; urgency=low
* Add tunnel mode with local port forwarding feature.
-- Max Lv <max.c.lv@gmail.com> Fri, 21 Feb 2014 11:52:13 +0900
shadowsocks (1.4.2-1) unstable; urgency=high shadowsocks (1.4.2-1) unstable; urgency=high
* Fix the UDP relay issues. * Fix the UDP relay issues.

27
src/Makefile.am

@ -6,7 +6,7 @@ AM_LDFLAGS = -static
SS_COMMON_LIBS = $(top_builddir)/libev/libev.la $(INET_NTOP_LIB) SS_COMMON_LIBS = $(top_builddir)/libev/libev.la $(INET_NTOP_LIB)
bin_PROGRAMS = ss-local
bin_PROGRAMS = ss-local ss-tunnel
if !BUILD_WINCOMPAT if !BUILD_WINCOMPAT
bin_PROGRAMS += ss-server bin_PROGRAMS += ss-server
@ -15,26 +15,39 @@ endif
ss_local_SOURCES = utils.c \ ss_local_SOURCES = utils.c \
jconf.c \ jconf.c \
json.c \ json.c \
encrypt.c \
udprelay.c \
cache.c \
local.c
encrypt.c \
udprelay.c \
cache.c \
local.c
ss_tunnel_SOURCES = utils.c \
jconf.c \
json.c \
encrypt.c \
udprelay.c \
cache.c \
tunnel.c
ss_server_SOURCES = utils.c \ ss_server_SOURCES = utils.c \
jconf.c \ jconf.c \
json.c \ json.c \
encrypt.c \ encrypt.c \
udprelay.c \
cache.c \
udprelay.c \
cache.c \
server.c server.c
ss_local_LDADD = $(SS_COMMON_LIBS) ss_local_LDADD = $(SS_COMMON_LIBS)
ss_tunnel_LDADD = $(SS_COMMON_LIBS)
ss_server_LDADD = $(SS_COMMON_LIBS) ss_server_LDADD = $(SS_COMMON_LIBS)
ss_server_LDADD += $(top_builddir)/libasyncns/libasyncns.la ss_server_LDADD += $(top_builddir)/libasyncns/libasyncns.la
ss_local_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL ss_local_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL
ss_tunnel_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL -DUDPRELAY_TUNNEL
ss_server_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_REMOTE ss_server_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_REMOTE
if BUILD_WINCOMPAT if BUILD_WINCOMPAT
ss_local_SOURCES += win32.c ss_local_SOURCES += win32.c
ss_tunnel_SOURCES += win32.c
endif endif
if BUILD_REDIRECTOR if BUILD_REDIRECTOR

156
src/Makefile.in

@ -51,10 +51,12 @@ PRE_UNINSTALL = :
POST_UNINSTALL = : POST_UNINSTALL = :
build_triplet = @build@ build_triplet = @build@
host_triplet = @host@ host_triplet = @host@
bin_PROGRAMS = ss-local$(EXEEXT) $(am__EXEEXT_1) $(am__EXEEXT_2)
bin_PROGRAMS = ss-local$(EXEEXT) ss-tunnel$(EXEEXT) $(am__EXEEXT_1) \
$(am__EXEEXT_2)
@BUILD_WINCOMPAT_FALSE@am__append_1 = ss-server @BUILD_WINCOMPAT_FALSE@am__append_1 = ss-server
@BUILD_WINCOMPAT_TRUE@am__append_2 = win32.c @BUILD_WINCOMPAT_TRUE@am__append_2 = win32.c
@BUILD_REDIRECTOR_TRUE@am__append_3 = ss-redir
@BUILD_WINCOMPAT_TRUE@am__append_3 = win32.c
@BUILD_REDIRECTOR_TRUE@am__append_4 = ss-redir
subdir = src subdir = src
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@ -106,6 +108,19 @@ ss_server_DEPENDENCIES = $(am__DEPENDENCIES_2) \
ss_server_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ ss_server_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_server_CFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_server_CFLAGS) \
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
am__ss_tunnel_SOURCES_DIST = utils.c jconf.c json.c encrypt.c \
udprelay.c cache.c tunnel.c win32.c
@BUILD_WINCOMPAT_TRUE@am__objects_2 = ss_tunnel-win32.$(OBJEXT)
am_ss_tunnel_OBJECTS = ss_tunnel-utils.$(OBJEXT) \
ss_tunnel-jconf.$(OBJEXT) ss_tunnel-json.$(OBJEXT) \
ss_tunnel-encrypt.$(OBJEXT) ss_tunnel-udprelay.$(OBJEXT) \
ss_tunnel-cache.$(OBJEXT) ss_tunnel-tunnel.$(OBJEXT) \
$(am__objects_2)
ss_tunnel_OBJECTS = $(am_ss_tunnel_OBJECTS)
ss_tunnel_DEPENDENCIES = $(am__DEPENDENCIES_2)
ss_tunnel_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_tunnel_CFLAGS) \
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles am__depfiles_maybe = depfiles
@ -119,9 +134,11 @@ CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@ $(LDFLAGS) -o $@
SOURCES = $(ss_local_SOURCES) $(ss_redir_SOURCES) $(ss_server_SOURCES)
SOURCES = $(ss_local_SOURCES) $(ss_redir_SOURCES) $(ss_server_SOURCES) \
$(ss_tunnel_SOURCES)
DIST_SOURCES = $(am__ss_local_SOURCES_DIST) \ DIST_SOURCES = $(am__ss_local_SOURCES_DIST) \
$(am__ss_redir_SOURCES_DIST) $(ss_server_SOURCES)
$(am__ss_redir_SOURCES_DIST) $(ss_server_SOURCES) \
$(am__ss_tunnel_SOURCES_DIST)
am__can_run_installinfo = \ am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \ case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \ n|no|NO) false;; \
@ -255,18 +272,22 @@ AM_LDFLAGS = -static
SS_COMMON_LIBS = $(top_builddir)/libev/libev.la $(INET_NTOP_LIB) SS_COMMON_LIBS = $(top_builddir)/libev/libev.la $(INET_NTOP_LIB)
ss_local_SOURCES = utils.c jconf.c json.c encrypt.c udprelay.c cache.c \ ss_local_SOURCES = utils.c jconf.c json.c encrypt.c udprelay.c cache.c \
local.c $(am__append_2) local.c $(am__append_2)
ss_tunnel_SOURCES = utils.c jconf.c json.c encrypt.c udprelay.c \
cache.c tunnel.c $(am__append_3)
ss_server_SOURCES = utils.c \ ss_server_SOURCES = utils.c \
jconf.c \ jconf.c \
json.c \ json.c \
encrypt.c \ encrypt.c \
udprelay.c \
cache.c \
udprelay.c \
cache.c \
server.c server.c
ss_local_LDADD = $(SS_COMMON_LIBS) ss_local_LDADD = $(SS_COMMON_LIBS)
ss_tunnel_LDADD = $(SS_COMMON_LIBS)
ss_server_LDADD = $(SS_COMMON_LIBS) \ ss_server_LDADD = $(SS_COMMON_LIBS) \
$(top_builddir)/libasyncns/libasyncns.la $(top_builddir)/libasyncns/libasyncns.la
ss_local_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL ss_local_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL
ss_tunnel_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_LOCAL -DUDPRELAY_TUNNEL
ss_server_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_REMOTE ss_server_CFLAGS = $(AM_CFLAGS) -DUDPRELAY_REMOTE
@BUILD_REDIRECTOR_TRUE@ss_redir_SOURCES = utils.c \ @BUILD_REDIRECTOR_TRUE@ss_redir_SOURCES = utils.c \
@BUILD_REDIRECTOR_TRUE@ jconf.c \ @BUILD_REDIRECTOR_TRUE@ jconf.c \
@ -364,6 +385,9 @@ ss-redir$(EXEEXT): $(ss_redir_OBJECTS) $(ss_redir_DEPENDENCIES) $(EXTRA_ss_redir
ss-server$(EXEEXT): $(ss_server_OBJECTS) $(ss_server_DEPENDENCIES) $(EXTRA_ss_server_DEPENDENCIES) ss-server$(EXEEXT): $(ss_server_OBJECTS) $(ss_server_DEPENDENCIES) $(EXTRA_ss_server_DEPENDENCIES)
@rm -f ss-server$(EXEEXT) @rm -f ss-server$(EXEEXT)
$(ss_server_LINK) $(ss_server_OBJECTS) $(ss_server_LDADD) $(LIBS) $(ss_server_LINK) $(ss_server_OBJECTS) $(ss_server_LDADD) $(LIBS)
ss-tunnel$(EXEEXT): $(ss_tunnel_OBJECTS) $(ss_tunnel_DEPENDENCIES) $(EXTRA_ss_tunnel_DEPENDENCIES)
@rm -f ss-tunnel$(EXEEXT)
$(ss_tunnel_LINK) $(ss_tunnel_OBJECTS) $(ss_tunnel_LDADD) $(LIBS)
mostlyclean-compile: mostlyclean-compile:
-rm -f *.$(OBJEXT) -rm -f *.$(OBJEXT)
@ -390,6 +414,14 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-server.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-udprelay.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-udprelay.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-utils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-utils.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_tunnel-cache.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_tunnel-encrypt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_tunnel-jconf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_tunnel-json.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_tunnel-tunnel.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_tunnel-udprelay.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_tunnel-utils.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_tunnel-win32.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@
.c.o: .c.o:
@ -623,6 +655,118 @@ ss_server-server.obj: server.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-server.obj `if test -f 'server.c'; then $(CYGPATH_W) 'server.c'; else $(CYGPATH_W) '$(srcdir)/server.c'; fi` @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-server.obj `if test -f 'server.c'; then $(CYGPATH_W) 'server.c'; else $(CYGPATH_W) '$(srcdir)/server.c'; fi`
ss_tunnel-utils.o: utils.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-utils.o -MD -MP -MF $(DEPDIR)/ss_tunnel-utils.Tpo -c -o ss_tunnel-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-utils.Tpo $(DEPDIR)/ss_tunnel-utils.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils.c' object='ss_tunnel-utils.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
ss_tunnel-utils.obj: utils.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-utils.obj -MD -MP -MF $(DEPDIR)/ss_tunnel-utils.Tpo -c -o ss_tunnel-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-utils.Tpo $(DEPDIR)/ss_tunnel-utils.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils.c' object='ss_tunnel-utils.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
ss_tunnel-jconf.o: jconf.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-jconf.o -MD -MP -MF $(DEPDIR)/ss_tunnel-jconf.Tpo -c -o ss_tunnel-jconf.o `test -f 'jconf.c' || echo '$(srcdir)/'`jconf.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-jconf.Tpo $(DEPDIR)/ss_tunnel-jconf.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='jconf.c' object='ss_tunnel-jconf.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-jconf.o `test -f 'jconf.c' || echo '$(srcdir)/'`jconf.c
ss_tunnel-jconf.obj: jconf.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-jconf.obj -MD -MP -MF $(DEPDIR)/ss_tunnel-jconf.Tpo -c -o ss_tunnel-jconf.obj `if test -f 'jconf.c'; then $(CYGPATH_W) 'jconf.c'; else $(CYGPATH_W) '$(srcdir)/jconf.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-jconf.Tpo $(DEPDIR)/ss_tunnel-jconf.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='jconf.c' object='ss_tunnel-jconf.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-jconf.obj `if test -f 'jconf.c'; then $(CYGPATH_W) 'jconf.c'; else $(CYGPATH_W) '$(srcdir)/jconf.c'; fi`
ss_tunnel-json.o: json.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-json.o -MD -MP -MF $(DEPDIR)/ss_tunnel-json.Tpo -c -o ss_tunnel-json.o `test -f 'json.c' || echo '$(srcdir)/'`json.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-json.Tpo $(DEPDIR)/ss_tunnel-json.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='json.c' object='ss_tunnel-json.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-json.o `test -f 'json.c' || echo '$(srcdir)/'`json.c
ss_tunnel-json.obj: json.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-json.obj -MD -MP -MF $(DEPDIR)/ss_tunnel-json.Tpo -c -o ss_tunnel-json.obj `if test -f 'json.c'; then $(CYGPATH_W) 'json.c'; else $(CYGPATH_W) '$(srcdir)/json.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-json.Tpo $(DEPDIR)/ss_tunnel-json.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='json.c' object='ss_tunnel-json.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-json.obj `if test -f 'json.c'; then $(CYGPATH_W) 'json.c'; else $(CYGPATH_W) '$(srcdir)/json.c'; fi`
ss_tunnel-encrypt.o: encrypt.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-encrypt.o -MD -MP -MF $(DEPDIR)/ss_tunnel-encrypt.Tpo -c -o ss_tunnel-encrypt.o `test -f 'encrypt.c' || echo '$(srcdir)/'`encrypt.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-encrypt.Tpo $(DEPDIR)/ss_tunnel-encrypt.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encrypt.c' object='ss_tunnel-encrypt.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-encrypt.o `test -f 'encrypt.c' || echo '$(srcdir)/'`encrypt.c
ss_tunnel-encrypt.obj: encrypt.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-encrypt.obj -MD -MP -MF $(DEPDIR)/ss_tunnel-encrypt.Tpo -c -o ss_tunnel-encrypt.obj `if test -f 'encrypt.c'; then $(CYGPATH_W) 'encrypt.c'; else $(CYGPATH_W) '$(srcdir)/encrypt.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-encrypt.Tpo $(DEPDIR)/ss_tunnel-encrypt.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='encrypt.c' object='ss_tunnel-encrypt.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-encrypt.obj `if test -f 'encrypt.c'; then $(CYGPATH_W) 'encrypt.c'; else $(CYGPATH_W) '$(srcdir)/encrypt.c'; fi`
ss_tunnel-udprelay.o: udprelay.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-udprelay.o -MD -MP -MF $(DEPDIR)/ss_tunnel-udprelay.Tpo -c -o ss_tunnel-udprelay.o `test -f 'udprelay.c' || echo '$(srcdir)/'`udprelay.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-udprelay.Tpo $(DEPDIR)/ss_tunnel-udprelay.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='udprelay.c' object='ss_tunnel-udprelay.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-udprelay.o `test -f 'udprelay.c' || echo '$(srcdir)/'`udprelay.c
ss_tunnel-udprelay.obj: udprelay.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-udprelay.obj -MD -MP -MF $(DEPDIR)/ss_tunnel-udprelay.Tpo -c -o ss_tunnel-udprelay.obj `if test -f 'udprelay.c'; then $(CYGPATH_W) 'udprelay.c'; else $(CYGPATH_W) '$(srcdir)/udprelay.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-udprelay.Tpo $(DEPDIR)/ss_tunnel-udprelay.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='udprelay.c' object='ss_tunnel-udprelay.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-udprelay.obj `if test -f 'udprelay.c'; then $(CYGPATH_W) 'udprelay.c'; else $(CYGPATH_W) '$(srcdir)/udprelay.c'; fi`
ss_tunnel-cache.o: cache.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-cache.o -MD -MP -MF $(DEPDIR)/ss_tunnel-cache.Tpo -c -o ss_tunnel-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-cache.Tpo $(DEPDIR)/ss_tunnel-cache.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cache.c' object='ss_tunnel-cache.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
ss_tunnel-cache.obj: cache.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-cache.obj -MD -MP -MF $(DEPDIR)/ss_tunnel-cache.Tpo -c -o ss_tunnel-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-cache.Tpo $(DEPDIR)/ss_tunnel-cache.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cache.c' object='ss_tunnel-cache.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi`
ss_tunnel-tunnel.o: tunnel.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-tunnel.o -MD -MP -MF $(DEPDIR)/ss_tunnel-tunnel.Tpo -c -o ss_tunnel-tunnel.o `test -f 'tunnel.c' || echo '$(srcdir)/'`tunnel.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-tunnel.Tpo $(DEPDIR)/ss_tunnel-tunnel.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tunnel.c' object='ss_tunnel-tunnel.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-tunnel.o `test -f 'tunnel.c' || echo '$(srcdir)/'`tunnel.c
ss_tunnel-tunnel.obj: tunnel.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-tunnel.obj -MD -MP -MF $(DEPDIR)/ss_tunnel-tunnel.Tpo -c -o ss_tunnel-tunnel.obj `if test -f 'tunnel.c'; then $(CYGPATH_W) 'tunnel.c'; else $(CYGPATH_W) '$(srcdir)/tunnel.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-tunnel.Tpo $(DEPDIR)/ss_tunnel-tunnel.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tunnel.c' object='ss_tunnel-tunnel.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-tunnel.obj `if test -f 'tunnel.c'; then $(CYGPATH_W) 'tunnel.c'; else $(CYGPATH_W) '$(srcdir)/tunnel.c'; fi`
ss_tunnel-win32.o: win32.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-win32.o -MD -MP -MF $(DEPDIR)/ss_tunnel-win32.Tpo -c -o ss_tunnel-win32.o `test -f 'win32.c' || echo '$(srcdir)/'`win32.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-win32.Tpo $(DEPDIR)/ss_tunnel-win32.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='win32.c' object='ss_tunnel-win32.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-win32.o `test -f 'win32.c' || echo '$(srcdir)/'`win32.c
ss_tunnel-win32.obj: win32.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -MT ss_tunnel-win32.obj -MD -MP -MF $(DEPDIR)/ss_tunnel-win32.Tpo -c -o ss_tunnel-win32.obj `if test -f 'win32.c'; then $(CYGPATH_W) 'win32.c'; else $(CYGPATH_W) '$(srcdir)/win32.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ss_tunnel-win32.Tpo $(DEPDIR)/ss_tunnel-win32.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='win32.c' object='ss_tunnel-win32.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_tunnel_CFLAGS) $(CFLAGS) -c -o ss_tunnel-win32.obj `if test -f 'win32.c'; then $(CYGPATH_W) 'win32.c'; else $(CYGPATH_W) '$(srcdir)/win32.c'; fi`
mostlyclean-libtool: mostlyclean-libtool:
-rm -f *.lo -rm -f *.lo

3
src/include.h

@ -4,6 +4,9 @@
int udprelay_init(const char *server_host, const char *server_port, int udprelay_init(const char *server_host, const char *server_port,
#ifdef UDPRELAY_LOCAL #ifdef UDPRELAY_LOCAL
const char *remote_host, const char *remote_port, const char *remote_host, const char *remote_port,
#ifdef UDPRELAY_TUNNEL
const addr_t tunnel_addr,
#endif
#endif #endif
#ifdef UDPRELAY_REMOTE #ifdef UDPRELAY_REMOTE
asyncns_t *asyncns, asyncns_t *asyncns,

15
src/jconf.c

@ -35,7 +35,16 @@ static char *to_string(const json_value *value)
return 0; return 0;
} }
static void parse_addr(const char *str, remote_addr_t *addr) {
void free_addr(addr_t *addr)
{
free(addr->host);
free(addr->port);
addr->host = NULL;
addr->port = NULL;
}
void parse_addr(const char *str, addr_t *addr)
{
int ret = -1, n = 0; int ret = -1, n = 0;
char *pch; char *pch;
pch = strchr(str, ':'); pch = strchr(str, ':');
@ -52,13 +61,13 @@ static void parse_addr(const char *str, remote_addr_t *addr) {
} }
if (ret == -1) if (ret == -1)
{ {
addr->host = str;
addr->host = strdup(str);
addr->port = NULL; addr->port = NULL;
} }
else else
{ {
addr->host = ss_strndup(str, ret); addr->host = ss_strndup(str, ret);
addr->port = str + ret + 1;
addr->port = strdup(str + ret + 1);
} }
} }

10
src/jconf.h

@ -8,14 +8,14 @@
typedef struct typedef struct
{ {
const char *host;
const char *port;
} remote_addr_t;
char *host;
char *port;
} addr_t;
typedef struct typedef struct
{ {
int remote_num; int remote_num;
remote_addr_t remote_addr[MAX_REMOTE_NUM];
addr_t remote_addr[MAX_REMOTE_NUM];
char *remote_port; char *remote_port;
char *local_addr; char *local_addr;
char *local_port; char *local_port;
@ -25,5 +25,7 @@ typedef struct
} jconf_t; } jconf_t;
jconf_t *read_jconf(const char* file); jconf_t *read_jconf(const char* file);
void parse_addr(const char *str, addr_t *addr);
void free_addr(addr_t *addr);
#endif // _JCONF_H #endif // _JCONF_H

5
src/local.c

@ -766,7 +766,6 @@ static void accept_cb (EV_P_ ev_io *w, int revents)
if (sockfd < 0) if (sockfd < 0)
{ {
ERROR("socket"); ERROR("socket");
close(sockfd);
freeaddrinfo(res); freeaddrinfo(res);
return; return;
} }
@ -808,7 +807,7 @@ int main (int argc, char **argv)
char *iface = NULL; char *iface = NULL;
int remote_num = 0; int remote_num = 0;
remote_addr_t remote_addr[MAX_REMOTE_NUM];
addr_t remote_addr[MAX_REMOTE_NUM];
char *remote_port = NULL; char *remote_port = NULL;
opterr = 0; opterr = 0;
@ -929,7 +928,7 @@ int main (int argc, char **argv)
// Setup proxy context // Setup proxy context
struct listen_ctx listen_ctx; struct listen_ctx listen_ctx;
listen_ctx.remote_num = remote_num; listen_ctx.remote_num = remote_num;
listen_ctx.remote_addr = malloc(sizeof(remote_addr_t) * remote_num);
listen_ctx.remote_addr = malloc(sizeof(addr_t) * remote_num);
while (remote_num > 0) while (remote_num > 0)
{ {
int index = --remote_num; int index = --remote_num;

2
src/local.h

@ -10,7 +10,7 @@
struct listen_ctx struct listen_ctx
{ {
ev_io io; ev_io io;
remote_addr_t *remote_addr;
addr_t *remote_addr;
char *iface; char *iface;
int remote_num; int remote_num;
int method; int method;

5
src/redir.c

@ -630,7 +630,6 @@ static void accept_cb (EV_P_ ev_io *w, int revents)
if (sockfd < 0) if (sockfd < 0)
{ {
ERROR("socket"); ERROR("socket");
close(sockfd);
freeaddrinfo(res); freeaddrinfo(res);
return; return;
} }
@ -670,7 +669,7 @@ int main (int argc, char **argv)
char *conf_path = NULL; char *conf_path = NULL;
int remote_num = 0; int remote_num = 0;
remote_addr_t remote_addr[MAX_REMOTE_NUM];
addr_t remote_addr[MAX_REMOTE_NUM];
char *remote_port = NULL; char *remote_port = NULL;
opterr = 0; opterr = 0;
@ -778,7 +777,7 @@ int main (int argc, char **argv)
// Setup proxy context // Setup proxy context
struct listen_ctx listen_ctx; struct listen_ctx listen_ctx;
listen_ctx.remote_num = remote_num; listen_ctx.remote_num = remote_num;
listen_ctx.remote_addr = malloc(sizeof(remote_addr_t) * remote_num);
listen_ctx.remote_addr = malloc(sizeof(addr_t) * remote_num);
while (remote_num > 0) while (remote_num > 0)
{ {
int index = --remote_num; int index = --remote_num;

2
src/redir.h

@ -8,7 +8,7 @@
struct listen_ctx struct listen_ctx
{ {
ev_io io; ev_io io;
remote_addr_t *remote_addr;
addr_t *remote_addr;
int remote_num; int remote_num;
int timeout; int timeout;
int fd; int fd;

884
src/tunnel.c

@ -0,0 +1,884 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <locale.h>
#include <signal.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#ifndef __MINGW32__
#include <errno.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <pthread.h>
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_NET_IF_H) && defined(__linux__)
#include <net/if.h>
#include <sys/ioctl.h>
#define SET_INTERFACE
#endif
#ifdef __MINGW32__
#include "win32.h"
#endif
#include "utils.h"
#include "tunnel.h"
#ifndef EAGAIN
#define EAGAIN EWOULDBLOCK
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK EAGAIN
#endif
#ifndef BUF_SIZE
#define BUF_SIZE 512
#endif
int verbose = 0;
int udprelay = 0;
#ifndef __MINGW32__
static int setnonblocking(int fd)
{
int flags;
if (-1 ==(flags = fcntl(fd, F_GETFL, 0)))
flags = 0;
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
#endif
#ifdef SET_INTERFACE
int setinterface(int socket_fd, const char* interface_name)
{
struct ifreq interface;
memset(&interface, 0, sizeof(interface));
strncpy(interface.ifr_name, interface_name, IFNAMSIZ);
int res = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, &interface, sizeof(struct ifreq));
return res;
}
#endif
int create_and_bind(const char *addr, const char *port)
{
struct addrinfo hints;
struct addrinfo *result, *rp;
int s, listen_sock;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */
hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */
s = getaddrinfo(addr, port, &hints, &result);
if (s != 0)
{
LOGD("getaddrinfo: %s", gai_strerror(s));
return -1;
}
for (rp = result; rp != NULL; rp = rp->ai_next)
{
listen_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (listen_sock == -1)
continue;
int opt = 1;
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
setsockopt(listen_sock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
if (s == 0)
{
/* We managed to bind successfully! */
break;
}
else
{
ERROR("bind");
}
close(listen_sock);
}
if (rp == NULL)
{
LOGE("Could not bind");
return -1;
}
freeaddrinfo(result);
return listen_sock;
}
static void server_recv_cb (EV_P_ ev_io *w, int revents)
{
struct server_ctx *server_recv_ctx = (struct server_ctx *)w;
struct server *server = server_recv_ctx->server;
struct remote *remote = server->remote;
if (remote == NULL)
{
close_and_free_server(EV_A_ server);
return;
}
ssize_t r = recv(server->fd, remote->buf, BUF_SIZE, 0);
if (r == 0)
{
// connection closed
remote->buf_len = 0;
remote->buf_idx = 0;
close_and_free_server(EV_A_ server);
if (remote != NULL)
{
ev_io_start(EV_A_ &remote->send_ctx->io);
}
return;
}
else if(r < 0)
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
{
// no data
// continue to wait for recv
return;
}
else
{
ERROR("server recv");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
remote->buf = ss_encrypt(BUF_SIZE, remote->buf, &r, server->e_ctx);
if (remote->buf == NULL)
{
LOGE("invalid password or cipher");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
int s = send(remote->fd, remote->buf, r, 0);
if(s == -1)
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
{
// no data, wait for send
remote->buf_len = r;
remote->buf_idx = 0;
ev_io_stop(EV_A_ &server_recv_ctx->io);
ev_io_start(EV_A_ &remote->send_ctx->io);
return;
}
else
{
ERROR("send");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
else if(s < r)
{
remote->buf_len = r - s;
remote->buf_idx = s;
ev_io_stop(EV_A_ &server_recv_ctx->io);
ev_io_start(EV_A_ &remote->send_ctx->io);
return;
}
}
static void server_send_cb (EV_P_ ev_io *w, int revents)
{
struct server_ctx *server_send_ctx = (struct server_ctx *)w;
struct server *server = server_send_ctx->server;
struct remote *remote = server->remote;
if (server->buf_len == 0)
{
// close and free
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
else
{
// has data to send
ssize_t s = send(server->fd, server->buf + server->buf_idx,
server->buf_len, 0);
if (s < 0)
{
if (errno != EAGAIN && errno != EWOULDBLOCK)
{
ERROR("send");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
}
return;
}
else if (s < server->buf_len)
{
// partly sent, move memory, wait for the next time to send
server->buf_len -= s;
server->buf_idx += s;
return;
}
else
{
// all sent out, wait for reading
server->buf_len = 0;
server->buf_idx = 0;
ev_io_stop(EV_A_ &server_send_ctx->io);
if (remote != NULL)
{
ev_io_start(EV_A_ &remote->recv_ctx->io);
}
else
{
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
}
}
static void remote_timeout_cb(EV_P_ ev_timer *watcher, int revents)
{
struct remote_ctx *remote_ctx = (struct remote_ctx *) (((void*)watcher)
- sizeof(ev_io));
struct remote *remote = remote_ctx->remote;
struct server *server = remote->server;
LOGD("remote timeout");
ev_timer_stop(EV_A_ watcher);
if (server == NULL)
{
close_and_free_remote(EV_A_ remote);
return;
}
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
}
static void remote_recv_cb (EV_P_ ev_io *w, int revents)
{
struct remote_ctx *remote_recv_ctx = (struct remote_ctx *)w;
struct remote *remote = remote_recv_ctx->remote;
struct server *server = remote->server;
if (server == NULL)
{
close_and_free_remote(EV_A_ remote);
return;
}
ssize_t r = recv(remote->fd, server->buf, BUF_SIZE, 0);
if (r == 0)
{
// connection closed
server->buf_len = 0;
server->buf_idx = 0;
close_and_free_remote(EV_A_ remote);
if (server != NULL)
{
ev_io_start(EV_A_ &server->send_ctx->io);
}
return;
}
else if(r < 0)
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
{
// no data
// continue to wait for recv
return;
}
else
{
ERROR("remote recv");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
server->buf = ss_decrypt(BUF_SIZE, server->buf, &r, server->d_ctx);
if (server->buf == NULL)
{
LOGE("invalid password or cipher");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
int s = send(server->fd, server->buf, r, 0);
if (s == -1)
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
{
// no data, wait for send
server->buf_len = r;
server->buf_idx = 0;
ev_io_stop(EV_A_ &remote_recv_ctx->io);
ev_io_start(EV_A_ &server->send_ctx->io);
return;
}
else
{
ERROR("send");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
else if (s < r)
{
server->buf_len = r - s;
server->buf_idx = s;
ev_io_stop(EV_A_ &remote_recv_ctx->io);
ev_io_start(EV_A_ &server->send_ctx->io);
return;
}
}
static void remote_send_cb (EV_P_ ev_io *w, int revents)
{
struct remote_ctx *remote_send_ctx = (struct remote_ctx *)w;
struct remote *remote = remote_send_ctx->remote;
struct server *server = remote->server;
if (!remote_send_ctx->connected)
{
struct sockaddr_storage addr;
socklen_t len = sizeof addr;
int r = getpeername(remote->fd, (struct sockaddr*)&addr, &len);
if (r == 0)
{
remote_send_ctx->connected = 1;
ev_io_stop(EV_A_ &remote_send_ctx->io);
ev_timer_stop(EV_A_ &remote_send_ctx->watcher);
// send destaddr
char *addr_to_send = malloc(BUF_SIZE);
ssize_t addr_len = 0;
struct sockaddr *sa = &server->destaddr;
addr_to_send[addr_len++] = 1;
if (sa->sa_family == AF_INET)
{
// handle IPv4
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
size_t in_addr_len = sizeof(struct in_addr);
memcpy(addr_to_send + addr_len, &sin->sin_addr, in_addr_len);
addr_len += in_addr_len;
memcpy(addr_to_send + addr_len, &sin->sin_port, 2);
addr_len += 2;
}
else if (sa->sa_family == AF_INET6)
{
// handle IPv6
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
size_t in6_addr_len = sizeof(struct in6_addr);
memcpy(addr_to_send + addr_len, &sin6->sin6_addr, in6_addr_len);
addr_len += in6_addr_len;
memcpy(addr_to_send + addr_len, &sin6->sin6_port, 2);
addr_len += 2;
}
else
{
LOGE("unsupported addr type");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
addr_to_send = ss_encrypt(BUF_SIZE, addr_to_send, &addr_len, server->e_ctx);
if (addr_to_send == NULL)
{
LOGE("invalid password or cipher");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
int s = send(remote->fd, addr_to_send, addr_len, 0);
free(addr_to_send);
if (s < addr_len)
{
LOGE("failed to send remote addr.");
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
}
ev_io_start(EV_A_ &remote->recv_ctx->io);
ev_io_start(EV_A_ &server->recv_ctx->io);
return;
}
else
{
ERROR("getpeername");
// not connected
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
else
{
if (remote->buf_len == 0)
{
// close and free
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
else
{
// has data to send
ssize_t s = send(remote->fd, remote->buf + remote->buf_idx,
remote->buf_len, 0);
if (s < 0)
{
if (errno != EAGAIN && errno != EWOULDBLOCK)
{
ERROR("send");
// close and free
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
}
return;
}
else if (s < remote->buf_len)
{
// partly sent, move memory, wait for the next time to send
remote->buf_len -= s;
remote->buf_idx += s;
return;
}
else
{
// all sent out, wait for reading
remote->buf_len = 0;
remote->buf_idx = 0;
ev_io_stop(EV_A_ &remote_send_ctx->io);
if (server != NULL)
{
ev_io_start(EV_A_ &server->recv_ctx->io);
}
else
{
close_and_free_remote(EV_A_ remote);
close_and_free_server(EV_A_ server);
return;
}
}
}
}
}
struct remote* new_remote(int fd, int timeout)
{
struct remote *remote;
remote = malloc(sizeof(struct remote));
remote->buf = malloc(BUF_SIZE);
remote->recv_ctx = malloc(sizeof(struct remote_ctx));
remote->send_ctx = malloc(sizeof(struct remote_ctx));
remote->fd = fd;
ev_io_init(&remote->recv_ctx->io, remote_recv_cb, fd, EV_READ);
ev_io_init(&remote->send_ctx->io, remote_send_cb, fd, EV_WRITE);
ev_timer_init(&remote->send_ctx->watcher, remote_timeout_cb, timeout, 0);
remote->recv_ctx->remote = remote;
remote->recv_ctx->connected = 0;
remote->send_ctx->remote = remote;
remote->send_ctx->connected = 0;
remote->buf_len = 0;
remote->buf_idx = 0;
return remote;
}
static void free_remote(struct remote *remote)
{
if (remote != NULL)
{
if (remote->server != NULL)
{
remote->server->remote = NULL;
}
if (remote->buf)
{
free(remote->buf);
}
free(remote->recv_ctx);
free(remote->send_ctx);
free(remote);
}
}
static void close_and_free_remote(EV_P_ struct remote *remote)
{
if (remote != NULL)
{
ev_timer_stop(EV_A_ &remote->send_ctx->watcher);
ev_io_stop(EV_A_ &remote->send_ctx->io);
ev_io_stop(EV_A_ &remote->recv_ctx->io);
close(remote->fd);
free_remote(remote);
}
}
struct server* new_server(int fd, int method)
{
struct server *server;
server = malloc(sizeof(struct server));
server->buf = malloc(BUF_SIZE);
server->recv_ctx = malloc(sizeof(struct server_ctx));
server->send_ctx = malloc(sizeof(struct server_ctx));
server->fd = fd;
ev_io_init(&server->recv_ctx->io, server_recv_cb, fd, EV_READ);
ev_io_init(&server->send_ctx->io, server_send_cb, fd, EV_WRITE);
server->recv_ctx->server = server;
server->recv_ctx->connected = 0;
server->send_ctx->server = server;
server->send_ctx->connected = 0;
if (method)
{
server->e_ctx = malloc(sizeof(struct enc_ctx));
server->d_ctx = malloc(sizeof(struct enc_ctx));
enc_ctx_init(method, server->e_ctx, 1);
enc_ctx_init(method, server->d_ctx, 0);
}
else
{
server->e_ctx = NULL;
server->d_ctx = NULL;
}
server->buf_len = 0;
server->buf_idx = 0;
return server;
}
static void free_server(struct server *server)
{
if (server != NULL)
{
if (server->remote != NULL)
{
server->remote->server = NULL;
}
if (server->e_ctx != NULL)
{
cipher_context_release(&server->e_ctx->evp);
free(server->e_ctx);
}
if (server->d_ctx != NULL)
{
cipher_context_release(&server->d_ctx->evp);
free(server->d_ctx);
}
if (server->buf)
{
free(server->buf);
}
free(server->recv_ctx);
free(server->send_ctx);
free(server);
}
}
static void close_and_free_server(EV_P_ struct server *server)
{
if (server != NULL)
{
ev_io_stop(EV_A_ &server->send_ctx->io);
ev_io_stop(EV_A_ &server->recv_ctx->io);
close(server->fd);
free_server(server);
}
}
static void accept_cb (EV_P_ ev_io *w, int revents)
{
struct listen_ctx *listener = (struct listen_ctx *)w;
int serverfd = accept(listener->fd, NULL, NULL);
if (serverfd == -1)
{
ERROR("accept");
return;
}
setnonblocking(serverfd);
int opt = 1;
setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
struct addrinfo hints, *res, *dest;
int sockfd;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
int index = rand() % listener->remote_num;
if (verbose)
{
LOGD("connect to %s:%s", listener->remote_addr[index].host, listener->remote_addr[index].port);
}
int err = getaddrinfo(listener->remote_addr[index].host, listener->remote_addr[index].port, &hints, &res);
if (err)
{
ERROR("getaddrinfo");
return;
}
err = getaddrinfo(listener->tunnel_addr.host, listener->tunnel_addr.port, &hints, &dest);
if (err)
{
freeaddrinfo(res);
ERROR("getaddrinfo");
return;
}
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd < 0)
{
ERROR("socket");
freeaddrinfo(res);
freeaddrinfo(dest);
return;
}
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
// Setup
setnonblocking(sockfd);
#ifdef SET_INTERFACE
if (listener->iface) setinterface(sockfd, listener->iface);
#endif
struct server *server = new_server(serverfd, listener->method);
struct remote *remote = new_remote(sockfd, listener->timeout);
server->destaddr = *dest->ai_addr;
server->remote = remote;
remote->server = server;
connect(sockfd, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
freeaddrinfo(dest);
// listen to remote connected event
ev_io_start(EV_A_ &remote->send_ctx->io);
ev_timer_start(EV_A_ &remote->send_ctx->watcher);
}
int main (int argc, char **argv)
{
int i, c;
int pid_flags = 0;
char *local_port = NULL;
char *local_addr = NULL;
char *password = NULL;
char *timeout = NULL;
char *method = NULL;
char *pid_path = NULL;
char *conf_path = NULL;
char *iface = NULL;
int remote_num = 0;
addr_t remote_addr[MAX_REMOTE_NUM];
char *remote_port = NULL;
addr_t tunnel_addr = {.host = NULL, .port = NULL};
char *tunnel_addr_str = NULL;
opterr = 0;
while ((c = getopt (argc, argv, "f:s:p:l:k:t:m:i:c:b:L:uv")) != -1)
{
switch (c)
{
case 's':
remote_addr[remote_num].host = optarg;
remote_addr[remote_num++].port = NULL;
break;
case 'p':
remote_port = optarg;
break;
case 'l':
local_port = optarg;
break;
case 'k':
password = optarg;
break;
case 'f':
pid_flags = 1;
pid_path = optarg;
break;
case 't':
timeout = optarg;
break;
case 'm':
method = optarg;
break;
case 'c':
conf_path = optarg;
break;
case 'i':
iface = optarg;
break;
case 'b':
local_addr = optarg;
break;
case 'u':
udprelay = 1;
break;
case 'L':
tunnel_addr_str = optarg;
break;
case 'v':
verbose = 1;
break;
}
}
if (opterr)
{
usage();
exit(EXIT_FAILURE);
}
if (conf_path != NULL)
{
jconf_t *conf = read_jconf(conf_path);
if (remote_num == 0)
{
remote_num = conf->remote_num;
for (i = 0; i < remote_num; i++)
{
remote_addr[i] = conf->remote_addr[i];
}
}
if (remote_port == NULL) remote_port = conf->remote_port;
if (local_addr == NULL) local_addr = conf->local_addr;
if (local_port == NULL) local_port = conf->local_port;
if (password == NULL) password = conf->password;
if (method == NULL) method = conf->method;
if (timeout == NULL) timeout = conf->timeout;
}
if (remote_num == 0 || remote_port == NULL || tunnel_addr_str == NULL ||
local_port == NULL || password == NULL)
{
usage();
exit(EXIT_FAILURE);
}
if (timeout == NULL) timeout = "10";
if (local_addr == NULL) local_addr = "0.0.0.0";
if (pid_flags)
{
USE_SYSLOG(argv[0]);
demonize(pid_path);
}
// parse tunnel addr
parse_addr(tunnel_addr_str, &tunnel_addr);
#ifdef __MINGW32__
winsock_init();
#else
// ignore SIGPIPE
signal(SIGPIPE, SIG_IGN);
signal(SIGABRT, SIG_IGN);
#endif
// Setup keys
LOGD("initialize ciphers... %s", method);
int m = enc_init(password, method);
// Setup socket
int listenfd;
listenfd = create_and_bind(local_addr, local_port);
if (listenfd < 0)
{
FATAL("bind() error..");
}
if (listen(listenfd, SOMAXCONN) == -1)
{
FATAL("listen() error.");
}
setnonblocking(listenfd);
LOGD("server listening at port %s.", local_port);
// Setup proxy context
struct listen_ctx listen_ctx;
listen_ctx.tunnel_addr = tunnel_addr;
listen_ctx.remote_num = remote_num;
listen_ctx.remote_addr = malloc(sizeof(addr_t) * remote_num);
while (remote_num > 0)
{
int index = --remote_num;
if (remote_addr[index].port == NULL) remote_addr[index].port = remote_port;
listen_ctx.remote_addr[index] = remote_addr[index];
}
listen_ctx.timeout = atoi(timeout);
listen_ctx.fd = listenfd;
listen_ctx.iface = iface;
listen_ctx.method = m;
struct ev_loop *loop = ev_default_loop(0);
if (!loop)
{
FATAL("ev_loop error.");
}
ev_io_init (&listen_ctx.io, accept_cb, listenfd, EV_READ);
ev_io_start (loop, &listen_ctx.io);
// Setup UDP
if (udprelay)
{
LOGD("udprelay enabled.");
udprelay_init(local_addr, local_port, remote_addr[0].host, remote_addr[0].port,
tunnel_addr, m, listen_ctx.timeout, iface);
}
ev_run (loop, 0);
#ifdef __MINGW32__
winsock_cleanup();
#endif
return 0;
}

76
src/tunnel.h

@ -0,0 +1,76 @@
#ifndef _LOCAL_H
#define _LOCAL_H
#include <ev.h>
#include "encrypt.h"
#include "jconf.h"
#include "include.h"
struct listen_ctx
{
ev_io io;
addr_t tunnel_addr;
addr_t *remote_addr;
char *iface;
int remote_num;
int method;
int timeout;
int fd;
struct sockaddr sock;
};
struct server_ctx
{
ev_io io;
int connected;
struct server *server;
};
struct server
{
int fd;
int buf_len;
int buf_idx;
char *buf; // server send from, remote recv into
struct enc_ctx *e_ctx;
struct enc_ctx *d_ctx;
struct server_ctx *recv_ctx;
struct server_ctx *send_ctx;
struct remote *remote;
struct sockaddr destaddr;
};
struct remote_ctx
{
ev_io io;
ev_timer watcher;
int connected;
struct remote *remote;
};
struct remote
{
int fd;
int buf_len;
int buf_idx;
char *buf; // remote send from, server recv into
struct remote_ctx *recv_ctx;
struct remote_ctx *send_ctx;
struct server *server;
};
static void accept_cb (EV_P_ ev_io *w, int revents);
static void server_recv_cb (EV_P_ ev_io *w, int revents);
static void server_send_cb (EV_P_ ev_io *w, int revents);
static void remote_recv_cb (EV_P_ ev_io *w, int revents);
static void remote_send_cb (EV_P_ ev_io *w, int revents);
static void free_remote(struct remote *remote);
static void close_and_free_remote(EV_P_ struct remote *remote);
static void free_server(struct server *server);
static void close_and_free_server(EV_P_ struct server *server);
struct remote* new_remote(int fd, int timeout);
struct server* new_server(int fd, int method);
#endif // _TUNNEL_H

48
src/udprelay.c

@ -473,6 +473,11 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents)
goto CLEAN_UP; goto CLEAN_UP;
} }
#ifdef UDPRELAY_TUNNEL
// Construct packet
buf_len -= addr_header_len;
memmove(buf, buf + addr_header_len, buf_len);
#else
// Construct packet // Construct packet
char *tmpbuf = malloc(buf_len + 3); char *tmpbuf = malloc(buf_len + 3);
memset(tmpbuf, 0, 3); memset(tmpbuf, 0, 3);
@ -481,6 +486,7 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents)
buf = tmpbuf; buf = tmpbuf;
buf_len += 3; buf_len += 3;
#endif #endif
#endif
#ifdef UDPRELAY_REMOTE #ifdef UDPRELAY_REMOTE
// Construct packet // Construct packet
@ -538,8 +544,10 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents)
#endif #endif
#ifdef UDPRELAY_LOCAL #ifdef UDPRELAY_LOCAL
#ifndef UDPRELAY_TUNNEL
uint8_t frag = *(uint8_t*)(buf + 2); uint8_t frag = *(uint8_t*)(buf + 2);
offset += 3; offset += 3;
#endif
#endif #endif
/* /*
@ -581,6 +589,29 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents)
* *
*/ */
#ifdef UDPRELAY_TUNNEL
char addr_header[256] = {0};
char* host = server_ctx->tunnel_addr.host;
char* port = server_ctx->tunnel_addr.port;
int host_len = strlen(host);
uint16_t port_num = (uint16_t)atoi(port);
uint16_t port_net_num = htons(port_num);
int addr_header_len = 2 + host_len + 2;
// initialize the addr header
addr_header[0] = 3;
addr_header[1] = host_len;
memcpy(addr_header + 2, host, host_len);
memcpy(addr_header + 2 + host_len, &port_net_num, 2);
// reconstruct the buffer
char *tmp = malloc(buf_len + addr_header_len);
memcpy(tmp, addr_header, addr_header_len);
memcpy(tmp + addr_header_len, buf, buf_len);
free(buf);
buf = tmp;
#else
char host[256] = {0}; char host[256] = {0};
char port[64] = {0}; char port[64] = {0};
@ -592,6 +623,8 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents)
goto CLEAN_UP; goto CLEAN_UP;
} }
char *addr_header = buf + offset; char *addr_header = buf + offset;
#endif
char *key = hash_key(addr_header, addr_header_len, &src_addr); char *key = hash_key(addr_header, addr_header_len, &src_addr);
struct cache *conn_cache = server_ctx->conn_cache; struct cache *conn_cache = server_ctx->conn_cache;
@ -615,11 +648,13 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents)
#ifdef UDPRELAY_LOCAL #ifdef UDPRELAY_LOCAL
#ifndef UDPRELAY_TUNNEL
if (frag) if (frag)
{ {
LOGE("drop a message since frag is not 0, but %d", frag); LOGE("drop a message since frag is not 0, but %d", frag);
goto CLEAN_UP; goto CLEAN_UP;
} }
#endif
if (remote_ctx == NULL) if (remote_ctx == NULL)
{ {
@ -675,8 +710,11 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents)
freeaddrinfo(result); freeaddrinfo(result);
} }
buf_len -= offset;
memmove(buf, buf + offset, buf_len);
if (offset > 0)
{
buf_len -= offset;
memmove(buf, buf + offset, buf_len);
}
buf = ss_encrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method); buf = ss_encrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method);
@ -750,6 +788,9 @@ void free_cb(void *element)
int udprelay_init(const char *server_host, const char *server_port, int udprelay_init(const char *server_host, const char *server_port,
#ifdef UDPRELAY_LOCAL #ifdef UDPRELAY_LOCAL
const char *remote_host, const char *remote_port, const char *remote_host, const char *remote_port,
#ifdef UDPRELAY_TUNNEL
const addr_t tunnel_addr,
#endif
#endif #endif
#ifdef UDPRELAY_REMOTE #ifdef UDPRELAY_REMOTE
asyncns_t *asyncns, asyncns_t *asyncns,
@ -783,6 +824,9 @@ int udprelay_init(const char *server_host, const char *server_port,
#ifdef UDPRELAY_LOCAL #ifdef UDPRELAY_LOCAL
server_ctx->remote_host = remote_host; server_ctx->remote_host = remote_host;
server_ctx->remote_port = remote_port; server_ctx->remote_port = remote_port;
#ifdef UDPRELAY_TUNNEL
server_ctx->tunnel_addr = tunnel_addr;
#endif
#endif #endif
#ifdef UDPRELAY_REMOTE #ifdef UDPRELAY_REMOTE
server_ctx->asyncns = asyncns; server_ctx->asyncns = asyncns;

3
src/udprelay.h

@ -32,6 +32,9 @@ struct server_ctx
#ifdef UDPRELAY_LOCAL #ifdef UDPRELAY_LOCAL
const char *remote_host; const char *remote_host;
const char *remote_port; const char *remote_port;
#ifdef UDPRELAY_TUNNEL
addr_t tunnel_addr;
#endif
#endif #endif
}; };

13
src/utils.c

@ -82,9 +82,10 @@ void usage()
{ {
printf("\n"); printf("\n");
printf("shadowsocks-libev %s\n\n", VERSION); printf("shadowsocks-libev %s\n\n", VERSION);
printf(" maintained by Max Lv <max.c.lv@gmail.com>\n\n");
printf(" maintained by Max Lv <max.c.lv@gmail.com>\n");
printf(" and Linus Yang <laokongzi@gmail.com>\n\n");
printf(" usage:\n\n"); printf(" usage:\n\n");
printf(" ss-[local|redir|server]\n");
printf(" ss-[local|redir|server|tunnel]\n");
printf(" -s <server_host> host name or ip address of your remote server\n"); printf(" -s <server_host> host name or ip address of your remote server\n");
printf(" -p <server_port> port number of your remote server\n"); printf(" -p <server_port> port number of your remote server\n");
printf(" -l <local_port> port number of your local server\n"); printf(" -l <local_port> port number of your local server\n");
@ -100,11 +101,13 @@ void usage()
printf(" [-c <config_file>] json format config file\n"); printf(" [-c <config_file>] json format config file\n");
printf("\n"); printf("\n");
printf(" [-i <interface>] specific network interface to bind,\n"); printf(" [-i <interface>] specific network interface to bind,\n");
printf(" only available in local and server modes\n");
printf(" not available in redir mode\n");
printf(" [-b <local_address>] specific local address to bind,\n"); printf(" [-b <local_address>] specific local address to bind,\n");
printf(" only available in local and redir modes\n");
printf(" not available in server mode\n");
printf(" [-u] udprelay mode to supprot udp traffic\n"); printf(" [-u] udprelay mode to supprot udp traffic\n");
printf(" only available in local and server modes\n");
printf(" not available in redir mode\n");
printf(" [-L <addr>:<port>] setup a local port forwarding tunnel\n");
printf(" only available in tunnel mode\n");
printf(" [-v] verbose mode, debug output in console\n"); printf(" [-v] verbose mode, debug output in console\n");
printf("\n"); printf("\n");
} }

Loading…
Cancel
Save