Add SSR lib
This commit is contained in:
parent
d407ddb1a1
commit
ef2f98a523
129
shadowsocks-libev/Makefile
Normal file
129
shadowsocks-libev/Makefile
Normal file
@ -0,0 +1,129 @@
|
||||
#
|
||||
# Copyright (C) 2017-2020 Yousong Zhou <yszhou4tech@gmail.com>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
# Checklist when bumping versions
|
||||
#
|
||||
# - update cipher list by checking src/crypto.c:crypto_init()
|
||||
# - check if default mode has changed from being tcp_only
|
||||
#
|
||||
PKG_NAME:=shadowsocks-libev
|
||||
PKG_VERSION:=3.3.5
|
||||
PKG_RELEASE:=9
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/shadowsocks/shadowsocks-libev/releases/download/v$(PKG_VERSION)
|
||||
PKG_HASH:=cfc8eded35360f4b67e18dc447b0c00cddb29cc57a3cec48b135e5fb87433488
|
||||
|
||||
PKG_MAINTAINER:=Yousong Zhou <yszhou4tech@gmail.com>
|
||||
|
||||
PKG_LICENSE:=GPL-3.0-or-later
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
||||
PKG_FIXUP:=autoreconf
|
||||
PKG_INSTALL:=1
|
||||
PKG_BUILD_FLAGS:=no-mips16 lto
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_BUILD_DEPENDS:=c-ares pcre
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
|
||||
define Package/shadowsocks-libev-config
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=Web Servers/Proxies
|
||||
TITLE:=shadowsocks-libev config scripts
|
||||
URL:=https://github.com/shadowsocks/shadowsocks-libev
|
||||
endef
|
||||
|
||||
define Package/shadowsocks-libev-config/conffiles
|
||||
/etc/config/shadowsocks-libev
|
||||
endef
|
||||
|
||||
define Package/shadowsocks-libev-config/install
|
||||
$(INSTALL_DIR) $(1)/etc/config
|
||||
$(INSTALL_DATA) ./files/shadowsocks-libev.config $(1)/etc/config/shadowsocks-libev
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/shadowsocks-libev.init $(1)/etc/init.d/shadowsocks-libev
|
||||
endef
|
||||
|
||||
|
||||
define Package/shadowsocks-libev/Default
|
||||
define Package/shadowsocks-libev-$(1)
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=Web Servers/Proxies
|
||||
TITLE:=shadowsocks-libev $(1)
|
||||
URL:=https://github.com/shadowsocks/shadowsocks-libev
|
||||
DEPENDS:=+libev +libmbedtls +libpthread +libsodium +shadowsocks-libev-config $(DEPENDS_$(1))
|
||||
endef
|
||||
|
||||
define Package/shadowsocks-libev-$(1)/install
|
||||
$$(INSTALL_DIR) $$(1)/usr/bin
|
||||
$$(INSTALL_BIN) $$(PKG_INSTALL_DIR)/usr/bin/$(1) $$(1)/usr/bin
|
||||
endef
|
||||
|
||||
endef
|
||||
|
||||
DEPENDS_ss-local = +libpcre
|
||||
DEPENDS_ss-server = +libcares +libpcre
|
||||
|
||||
SHADOWSOCKS_COMPONENTS:=ss-local ss-redir ss-tunnel ss-server
|
||||
define shadowsocks-libev/templates
|
||||
$(foreach component,$(SHADOWSOCKS_COMPONENTS),
|
||||
$(call Package/shadowsocks-libev/Default,$(component))
|
||||
)
|
||||
endef
|
||||
$(eval $(call shadowsocks-libev/templates))
|
||||
|
||||
|
||||
define Package/shadowsocks-libev-ss-rules
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=Web Servers/Proxies
|
||||
TITLE:=shadowsocks-libev ss-rules
|
||||
URL:=https://github.com/shadowsocks/shadowsocks-libev
|
||||
DEPENDS:=+firewall4 \
|
||||
+ip \
|
||||
+resolveip \
|
||||
+ucode \
|
||||
+ucode-mod-fs \
|
||||
+shadowsocks-libev-ss-redir \
|
||||
+shadowsocks-libev-config \
|
||||
+kmod-nft-tproxy
|
||||
endef
|
||||
|
||||
define Package/shadowsocks-libev-ss-rules/install
|
||||
$(INSTALL_DIR) $(1)/usr/share/ss-rules
|
||||
$(INSTALL_DATA) ./files/ss-rules/* $(1)/usr/share/ss-rules/
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
$(call Build/Prepare/Default)
|
||||
$(FIND) $(PKG_BUILD_DIR) \
|
||||
-name '*.o' \
|
||||
-o -name '*.lo' \
|
||||
-o -name '.deps' \
|
||||
-o -name '.libs' \
|
||||
| $(XARGS) rm -rvf
|
||||
endef
|
||||
|
||||
CONFIGURE_ARGS += \
|
||||
--disable-documentation \
|
||||
--disable-silent-rules \
|
||||
--disable-assert \
|
||||
--disable-ssp \
|
||||
|
||||
TARGET_LDFLAGS += -Wl,--gc-sections,--as-needed
|
||||
|
||||
$(eval $(call BuildPackage,shadowsocks-libev-config))
|
||||
$(eval $(call BuildPackage,shadowsocks-libev-ss-rules))
|
||||
$(foreach component,$(SHADOWSOCKS_COMPONENTS), \
|
||||
$(eval $(call BuildPackage,shadowsocks-libev-$(component))) \
|
||||
)
|
185
shadowsocks-libev/README.md
Normal file
185
shadowsocks-libev/README.md
Normal file
@ -0,0 +1,185 @@
|
||||
Skip to [recipes](#recipes) for quick setup instructions
|
||||
|
||||
# components
|
||||
|
||||
`ss-local` provides SOCKS5 proxy with UDP associate support.
|
||||
|
||||
socks5 ss plain
|
||||
--------> tcp:local_address:local_port ----> ss server -------> dest
|
||||
|
||||
`ss-redir`. The REDIRECT and TPROXY part are to be provided by `ss-rules` script. REDIRECT is for tcp traffic (`SO_ORIGINAL_DST` only supports TCP). TPROXY is for udp messages, but it's only available in the PREROUTING chain and as such cannot proxy local out traffic.
|
||||
|
||||
plain plain ss plain
|
||||
---------> REDIRECT ------> tcp:local_address:local_port ----> ss server -----> original dest
|
||||
|
||||
plain plain ss plain
|
||||
---------> TPROXY -------> udp:local_address:local_port -----> ss server -----> original dest
|
||||
|
||||
`ss-tunnel` provides ssh `-L` local-forwarding-like tunnel. Typically it's used to tunnel DNS traffic to the remote.
|
||||
|
||||
plain ss plain
|
||||
---------> tcp|udp:local_address:local_port ------> ss server -------> tunnel_address
|
||||
|
||||
`ss-server`, the "ss server" in the above diagram
|
||||
|
||||
# uci
|
||||
|
||||
Option names are the same as those used in json config files. Check `validate_xxx` func definition of the [service script](files/shadowsocks-libev.init) and shadowsocks-libev's own documentation for supported options and expected value types. A [sample config file](files/shadowsocks-libev.config) is also provided for reference.
|
||||
|
||||
Every section have a `disabled` option to temporarily turn off the component instance or component instances referring to it.
|
||||
|
||||
Section type `server` is for definition of remote shadowsocks servers. They will be referred to from other component sections and as such should be named (as compared to anonymous section).
|
||||
|
||||
Section type `ss_local`, `ss_redir`, `ss_tunnel` are for specification of shadowsocks-libev components. They share mostly a common set of options like `local_port`, `verbose`, `fast_open`, `timeout`, etc.
|
||||
|
||||
Plugin options should be specified in `server` section and will be inherited by other compoenents referring to it.
|
||||
|
||||
We can have multiple instances of component and `server` sections. The relationship between them is many-to-one. This will have the following implications
|
||||
|
||||
- It's possible to have both `ss_local` and `ss_redir` referring to the same `server` definition
|
||||
- It's possible to have multiple instances of `ss_redir` listening on the same address:port with `reuse_port` enabled referring to the same or different `server` sections
|
||||
|
||||
`ss_rules` section is for configuring the behaviour of `ss-rules` script. There can only exist at most one such section with the name also being `ss_rules`
|
||||
|
||||
redir_tcp name of ss_redir section with mode tcp_only or tcp_and_udp
|
||||
redir_udp name of ss_redir section with mode udp_only or tcp_and_udp
|
||||
ifnames only apply rules on packets from these ifnames
|
||||
|
||||
--- for incoming packets having source address in
|
||||
|
||||
src_ips_bypass will bypass the redir chain
|
||||
src_ips_forward will always go through the redir chain
|
||||
src_ips_checkdst will continue to have their destination addresses checked
|
||||
|
||||
--- otherwise, the default action can be specified with
|
||||
|
||||
src_default bypass, forward, [checkdst]
|
||||
|
||||
--- if the previous check result is checkdst,
|
||||
--- then packets having destination address in
|
||||
|
||||
dst_ips_bypass_file
|
||||
dst_ips_bypass will bypass the redir chain
|
||||
dst_ips_forward_file
|
||||
dst_ips_forward will go through the redir chain
|
||||
|
||||
--- otherwise, the default action can be specified with
|
||||
|
||||
dst_default [bypass], forward
|
||||
|
||||
--- for local out tcp packets, the default action can be specified with
|
||||
|
||||
local_default [bypass], forward, checkdst
|
||||
|
||||
ss-rules now uses nft set for storing addresses/networks. Those set names are also part of the API and can be populated by other programs, e.g. dnsmasq with builtin nft set support. Note that while nftables set supports storing cidr networks when `interval` flag is on, it rejects elements with overlaping intervals.
|
||||
|
||||
Extra nftables expressions can be specified with `nft_tcp_extra` and `nft_udp_extra` to apply ss_rules only to selected tcp/udp traffics. E.g. `tcp dport { 80, 443 }`, `udp dport 53`, etc.
|
||||
|
||||
# incompatible changes
|
||||
|
||||
| Commit date | Commit ID | Subject | Comment |
|
||||
| ----------- | --------- | ------- | ------- |
|
||||
| 2022-03-01 | fdaf2de2a | shadowsocks-libev: ss-rules: convert to using nft | ss-rules now uses nftables. UCI option ipt_args and dst_forward_recentrst are now deprecated and removed |
|
||||
| 2020-08-03 | 7d7cbae75 | shadowsocks-libev: support ss-server option local_address_{v4,v6} | ss_server bind_address now deprecated, use local_address |
|
||||
| 2019-05-09 | afe7d3424 | shadowsocks-libev: move plugin options to server section | This is a revision against c19e949 committed 2019-05-06 |
|
||||
| 2017-07-02 | b61af9703 | shadowsocks-libev: rewrite | Packaging of shadowsocks-libev was rewritten from scratch |
|
||||
|
||||
# notes and faq
|
||||
|
||||
Useful paths and commands for debugging
|
||||
|
||||
# check current running status
|
||||
ubus call service list '{"name": "shadowsocks-libev"}'
|
||||
ubus call service list '{"name": "shadowsocks-libev", "verbose": true}'
|
||||
|
||||
# dump validate definition
|
||||
ubus call service validate '{"package": "shadowsocks-libev"}'
|
||||
ubus call service validate '{"package": "shadowsocks-libev"}' \
|
||||
| jsonfilter -e '$["shadowsocks-libev"]["ss_tunnel"]'
|
||||
|
||||
# check json config
|
||||
ls -l /var/etc/shadowsocks-libev/
|
||||
|
||||
# set uci config option verbose to 1, restart the service and follow the log
|
||||
logread -f
|
||||
|
||||
ss-redir needs to open a new socket and setsockopt IP_TRANSPARENT when sending udp reply to client. This requires `CAP_NET_ADMIN` and as such the process cannot run as `nobody`
|
||||
|
||||
ss-local, ss-redir, etc. supports specifying an array of remote ss server, but supporting this in uci seems to be overkill. The workaround can be defining multiple `server` sections and multiple `ss-redir` instances with `reuse_port` enabled
|
||||
|
||||
# recipes
|
||||
|
||||
## forward all
|
||||
|
||||
This will setup firewall rules to forward almost all incoming tcp/udp and locally generated tcp traffic (excluding those to private addresses like 192.168.0.0/16 etc.) through remote shadowsocks server
|
||||
|
||||
Install components.
|
||||
Retry each command till it succeed
|
||||
|
||||
opkg install shadowsocks-libev-ss-redir
|
||||
opkg install shadowsocks-libev-ss-rules
|
||||
opkg install shadowsocks-libev-ss-tunnel
|
||||
|
||||
Edit uci config `/etc/config/shadowsocks-libev`.
|
||||
Replace `config server 'sss0'` section with parameters of your own remote shadowsocks server.
|
||||
As for other options, change them only when you know the effect.
|
||||
|
||||
config server 'sss0'
|
||||
option disabled 0
|
||||
option server '_sss_addr_'
|
||||
option server_port '_sss_port_'
|
||||
option password '********'
|
||||
option method 'aes-256-cfb'
|
||||
|
||||
config ss_tunnel
|
||||
option disabled 0
|
||||
option server 'sss0'
|
||||
option local_address '0.0.0.0'
|
||||
option local_port '8053'
|
||||
option tunnel_address '8.8.8.8:53'
|
||||
option mode 'tcp_and_udp'
|
||||
|
||||
config ss_redir ssr0
|
||||
option disabled 0
|
||||
option server 'sss0'
|
||||
option local_address '0.0.0.0'
|
||||
option local_port '1100'
|
||||
option mode 'tcp_and_udp'
|
||||
option reuse_port 1
|
||||
|
||||
config ss_rules 'ss_rules'
|
||||
option disabled 0
|
||||
option redir_tcp 'ssr0'
|
||||
option redir_udp 'ssr0'
|
||||
option src_default 'checkdst'
|
||||
option dst_default 'forward'
|
||||
option local_default 'forward'
|
||||
|
||||
Restart shadowsocks-libev components
|
||||
|
||||
/etc/init.d/shadowsocks-libev restart
|
||||
|
||||
Check if things are in place
|
||||
|
||||
nft list ruleset | sed -r -n '/^\t[a-z]+ ss_rules[^ ]+ \{/,/^\t\}/p'
|
||||
netstat -lntp | grep -E '8053|1100'
|
||||
ps ww | grep ss-
|
||||
|
||||
Edit `/etc/config/dhcp`, making sure options are present in the first dnsmasq section like the following to let it use local tunnel endpoint for upstream dns query.
|
||||
Option `noresolv` instructs dnsmasq to not use other dns servers like advertised by local isp.
|
||||
Option `localuse` intends to make sure the device you are configuring also uses this dnsmasq instance as the resolver, not the ones from other sources.
|
||||
|
||||
config dnsmasq
|
||||
...
|
||||
list server '127.0.0.1#8053'
|
||||
option noresolv 1
|
||||
option localuse 1
|
||||
|
||||
Restart dnsmasq
|
||||
|
||||
/etc/init.d/dnsmasq restart
|
||||
|
||||
Check network on your computer
|
||||
|
||||
nslookup www.google.com
|
||||
curl -vv https://www.google.com
|
60
shadowsocks-libev/files/shadowsocks-libev.config
Normal file
60
shadowsocks-libev/files/shadowsocks-libev.config
Normal file
@ -0,0 +1,60 @@
|
||||
config ss_local
|
||||
option disabled 1
|
||||
option server 'sss0'
|
||||
option local_address '0.0.0.0'
|
||||
option local_port '1080'
|
||||
option timeout '30'
|
||||
|
||||
config ss_tunnel
|
||||
option disabled 1
|
||||
option server 'sss0'
|
||||
option local_address '0.0.0.0'
|
||||
option local_port '1090'
|
||||
option tunnel_address 'example.com:80'
|
||||
option mode 'tcp_and_udp'
|
||||
option timeout '60'
|
||||
|
||||
config ss_redir hi
|
||||
option disabled 1
|
||||
option server 'sss0'
|
||||
option local_address '0.0.0.0'
|
||||
option local_port '1100'
|
||||
option mode 'tcp_and_udp'
|
||||
option timeout '60'
|
||||
option fast_open 1
|
||||
option verbose 1
|
||||
option reuse_port 1
|
||||
|
||||
config ss_redir hj
|
||||
option disabled 1
|
||||
option server 'sss0'
|
||||
option local_address '0.0.0.0'
|
||||
option local_port '1100'
|
||||
option mode 'tcp_and_udp'
|
||||
option timeout '60'
|
||||
option fast_open 1
|
||||
option verbose 1
|
||||
option reuse_port 1
|
||||
|
||||
config ss_rules 'ss_rules'
|
||||
option disabled 1
|
||||
option redir_tcp 'hi'
|
||||
option redir_udp 'hi'
|
||||
option src_default 'checkdst'
|
||||
option dst_default 'bypass'
|
||||
option local_default 'checkdst'
|
||||
list src_ips_forward '192.168.1.4'
|
||||
list dst_ips_forward '8.8.8.8'
|
||||
|
||||
config server 'sss0'
|
||||
option disabled 1
|
||||
option server '192.168.1.3'
|
||||
option server_port '9001'
|
||||
option password '********'
|
||||
option method 'aes-256-cfb'
|
||||
|
||||
config ss_server
|
||||
option disabled 1
|
||||
option server_port '9001'
|
||||
option password '********'
|
||||
option method 'aes-256-cfb'
|
320
shadowsocks-libev/files/shadowsocks-libev.init
Normal file
320
shadowsocks-libev/files/shadowsocks-libev.init
Normal file
@ -0,0 +1,320 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
#
|
||||
# Copyright (C) 2017-2019 Yousong Zhou <yszhou4tech@gmail.com>
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v3.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
USE_PROCD=1
|
||||
START=99
|
||||
|
||||
ss_confdir=/var/etc/shadowsocks-libev
|
||||
ss_bindir=/usr/bin
|
||||
|
||||
ssrules_uc="/usr/share/ss-rules/ss-rules.uc"
|
||||
ssrules_nft="/etc/nftables.d/90-ss-rules.nft"
|
||||
|
||||
ss_mkjson_server_conf() {
|
||||
local cfgserver
|
||||
|
||||
config_get cfgserver "$cfg" server
|
||||
[ -n "$cfgserver" ] || return 1
|
||||
eval "$(validate_server_section "$cfg" ss_validate_mklocal)"
|
||||
validate_server_section "$cfgserver" || return 1
|
||||
[ "$disabled" = 0 ] || return 1
|
||||
ss_mkjson_server_conf_ "$cfgserver"
|
||||
}
|
||||
|
||||
ss_mkjson_server_conf_() {
|
||||
[ -n "$server_port" ] || return 1
|
||||
[ -z "$server" ] || json_add_string server "$server"
|
||||
json_add_int server_port "$server_port"
|
||||
[ -z "$method" ] || json_add_string method "$method"
|
||||
[ -z "$key" ] || json_add_string key "$key"
|
||||
[ -z "$password" ] || json_add_string password "$password"
|
||||
[ -z "$plugin" ] || json_add_string plugin "$plugin"
|
||||
[ -z "$plugin_opts" ] || json_add_string plugin_opts "$plugin_opts"
|
||||
}
|
||||
|
||||
ss_mkjson_ss_local_conf() {
|
||||
ss_mkjson_server_conf
|
||||
}
|
||||
|
||||
ss_mkjson_ss_redir_conf() {
|
||||
ss_mkjson_server_conf
|
||||
}
|
||||
|
||||
ss_mkjson_ss_server_conf() {
|
||||
ss_mkjson_server_conf_
|
||||
}
|
||||
|
||||
ss_mkjson_ss_tunnel_conf() {
|
||||
ss_mkjson_server_conf || return 1
|
||||
[ -n "$tunnel_address" ] || return 1
|
||||
json_add_string tunnel_address "$tunnel_address"
|
||||
}
|
||||
|
||||
ss_xxx() {
|
||||
local cfg="$1"
|
||||
local cfgtype="$2"
|
||||
local bin="$ss_bindir/${cfgtype/_/-}"
|
||||
local confjson="$ss_confdir/$cfgtype.$cfg.json"
|
||||
|
||||
[ -x "$bin" ] || return
|
||||
eval "$("validate_${cfgtype}_section" "$cfg" ss_validate_mklocal)"
|
||||
"validate_${cfgtype}_section" "$cfg" || return
|
||||
[ "$disabled" = 0 ] || return
|
||||
|
||||
json_init
|
||||
ss_mkjson_${cfgtype}_conf || return
|
||||
json_add_boolean use_syslog 1
|
||||
json_add_boolean ipv6_first "$ipv6_first"
|
||||
json_add_boolean fast_open "$fast_open"
|
||||
json_add_boolean reuse_port "$reuse_port"
|
||||
json_add_boolean no_delay "$no_delay"
|
||||
[ -z "$local_address" ] || json_add_string local_address "$local_address"
|
||||
[ -z "$local_port" ] || json_add_int local_port "$local_port"
|
||||
[ -z "$local_ipv4_address" ] || json_add_string local_ipv4_address "$local_ipv4_address"
|
||||
[ -z "$local_ipv6_address" ] || json_add_string local_ipv6_address "$local_ipv6_address"
|
||||
[ -z "$mode" ] || json_add_string mode "$mode"
|
||||
[ -z "$mtu" ] || json_add_int mtu "$mtu"
|
||||
[ -z "$timeout" ] || json_add_int timeout "$timeout"
|
||||
[ -z "$user" ] || json_add_string user "$user"
|
||||
[ -z "$acl" ] || json_add_string acl "$acl"
|
||||
json_dump -i >"$confjson"
|
||||
|
||||
procd_open_instance "$cfgtype.$cfg"
|
||||
procd_set_param command "$bin" -c "$confjson"
|
||||
[ "$verbose" = 0 ] || procd_append_param command -v
|
||||
if [ -n "$bind_address" ]; then
|
||||
echo "$cfgtype $cfg: uci option bind_address deprecated, please switch to local_address" >&2
|
||||
procd_append_param command -b "$bind_address"
|
||||
fi
|
||||
procd_set_param file "$confjson"
|
||||
procd_set_param respawn
|
||||
procd_close_instance
|
||||
ss_rules_cb
|
||||
}
|
||||
|
||||
ss_rules_cb() {
|
||||
local cfgserver server
|
||||
|
||||
if [ "$cfgtype" = ss_redir ]; then
|
||||
config_get cfgserver "$cfg" server
|
||||
config_get server "$cfgserver" server
|
||||
ss_redir_servers="$ss_redir_servers $server"
|
||||
if [ "$mode" = tcp_only -o "$mode" = "tcp_and_udp" ]; then
|
||||
eval "ss_rules_redir_tcp_$cfg=$local_port"
|
||||
fi
|
||||
if [ "$mode" = udp_only -o "$mode" = "tcp_and_udp" ]; then
|
||||
eval "ss_rules_redir_udp_$cfg=$local_port"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
ss_rules_nft_gen() {
|
||||
local cfg="ss_rules"
|
||||
local cfgtype
|
||||
local local_port_tcp local_port_udp
|
||||
local remote_servers
|
||||
|
||||
[ -s "$ssrules_uc" ] || return 1
|
||||
|
||||
config_get cfgtype "$cfg" TYPE
|
||||
[ "$cfgtype" = ss_rules ] || return 1
|
||||
|
||||
eval "$(validate_ss_rules_section "$cfg" ss_validate_mklocal)"
|
||||
validate_ss_rules_section "$cfg" || return 1
|
||||
[ "$disabled" = 0 ] || return 2
|
||||
|
||||
eval local_port_tcp="\$ss_rules_redir_tcp_$redir_tcp"
|
||||
eval local_port_udp="\$ss_rules_redir_udp_$redir_udp"
|
||||
[ -n "$local_port_tcp" -o -n "$local_port_udp" ] || return 1
|
||||
remote_servers="$(echo $ss_redir_servers \
|
||||
| tr ' ' '\n' \
|
||||
| sort -u \
|
||||
| xargs -n 1 resolveip \
|
||||
| sort -u)"
|
||||
|
||||
local tmp="/tmp/ssrules"
|
||||
json_init
|
||||
json_add_string o_remote_servers "$remote_servers"
|
||||
json_add_int o_redir_tcp_port "$local_port_tcp"
|
||||
json_add_int o_redir_udp_port "$local_port_udp"
|
||||
json_add_string o_ifnames "$ifnames"
|
||||
json_add_string o_local_default "$local_default"
|
||||
json_add_string o_src_bypass "$src_ips_bypass"
|
||||
json_add_string o_src_forward "$src_ips_forward"
|
||||
json_add_string o_src_checkdst "$src_ips_checkdst"
|
||||
json_add_string o_src_default "$src_default"
|
||||
json_add_string o_dst_bypass "$dst_ips_bypass"
|
||||
json_add_string o_dst_forward "$dst_ips_forward"
|
||||
json_add_string o_dst_bypass_file "$dst_ips_bypass_file"
|
||||
json_add_string o_dst_forward_file "$dst_ips_forward_file"
|
||||
json_add_string o_dst_default "$dst_default"
|
||||
json_add_string o_nft_tcp_extra "$nft_tcp_extra"
|
||||
json_add_string o_nft_udp_extra "$nft_udp_extra"
|
||||
json_dump -i >"$tmp.json"
|
||||
|
||||
if utpl -S -F "$tmp.json" "$ssrules_uc" >"$tmp.nft" \
|
||||
&& ! cmp -s "$tmp.nft" "$ssrules_nft"; then
|
||||
echo "table inet chk {include \"$tmp.nft\";}" >"$tmp.nft.chk"
|
||||
if nft -f "$tmp.nft.chk" -c; then
|
||||
mv "$tmp.nft" "$ssrules_nft"
|
||||
fw4 restart
|
||||
fi
|
||||
rm -f "$tmp.nft.chk"
|
||||
fi
|
||||
rm -f "$tmp.json"
|
||||
rm -f "$tmp.nft"
|
||||
}
|
||||
|
||||
ss_rules_nft_reset() {
|
||||
if [ -f "$ssrules_nft" ]; then
|
||||
rm -f "$ssrules_nft"
|
||||
fw4 restart
|
||||
fi
|
||||
}
|
||||
|
||||
ss_rules() {
|
||||
if ! ss_rules_nft_gen; then
|
||||
ss_rules_nft_reset
|
||||
fi
|
||||
}
|
||||
|
||||
start_service() {
|
||||
local cfgtype
|
||||
|
||||
mkdir -p "$ss_confdir"
|
||||
config_load shadowsocks-libev
|
||||
for cfgtype in ss_local ss_redir ss_server ss_tunnel; do
|
||||
config_foreach ss_xxx "$cfgtype" "$cfgtype"
|
||||
done
|
||||
ss_rules
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
ss_rules_nft_reset
|
||||
rm -rf "$ss_confdir"
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_interface_trigger wan
|
||||
procd_add_reload_trigger shadowsocks-libev
|
||||
procd_open_validate
|
||||
validate_server_section
|
||||
validate_ss_local_section
|
||||
validate_ss_redir_section
|
||||
validate_ss_rules_section
|
||||
validate_ss_server_section
|
||||
validate_ss_tunnel_section
|
||||
procd_close_validate
|
||||
}
|
||||
|
||||
ss_validate_mklocal() {
|
||||
local tuple opts
|
||||
|
||||
shift 2
|
||||
for tuple in "$@"; do
|
||||
opts="${tuple%%:*} $opts"
|
||||
done
|
||||
[ -z "$opts" ] || echo "local $opts"
|
||||
}
|
||||
|
||||
ss_validate() {
|
||||
uci_validate_section shadowsocks-libev "$@"
|
||||
}
|
||||
|
||||
validate_common_server_options_() {
|
||||
local cfgtype="$1"; shift
|
||||
local cfg="$1"; shift
|
||||
local func="$1"; shift
|
||||
local stream_methods='"table", "rc4", "rc4-md5", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "bf-cfb", "camellia-128-cfb", "camellia-192-cfb", "camellia-256-cfb", "salsa20", "chacha20", "chacha20-ietf"'
|
||||
local aead_methods='"aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305"'
|
||||
|
||||
"${func:-ss_validate}" "$cfgtype" "$cfg" "$@" \
|
||||
'disabled:bool:0' \
|
||||
'server:host' \
|
||||
'server_port:port' \
|
||||
'password:string' \
|
||||
'key:string' \
|
||||
"method:or($stream_methods, $aead_methods)" \
|
||||
'plugin:string' \
|
||||
'plugin_opts:string'
|
||||
}
|
||||
|
||||
validate_common_client_options_() {
|
||||
validate_common_options_ "$@" \
|
||||
'server:uci("shadowsocks-libev", "@server")' \
|
||||
'local_address:ipaddr:0.0.0.0' \
|
||||
'local_port:port'
|
||||
}
|
||||
|
||||
validate_common_options_() {
|
||||
local cfgtype="$1"; shift
|
||||
local cfg="$1"; shift
|
||||
local func="$1"; shift
|
||||
|
||||
"${func:-ss_validate}" "$cfgtype" "$cfg" "$@" \
|
||||
'disabled:bool:0' \
|
||||
'fast_open:bool:0' \
|
||||
'ipv6_first:bool:0' \
|
||||
'no_delay:bool:0' \
|
||||
'reuse_port:bool:0' \
|
||||
'verbose:bool:0' \
|
||||
'mode:or("tcp_only", "udp_only", "tcp_and_udp"):tcp_only' \
|
||||
'mtu:uinteger' \
|
||||
'timeout:uinteger' \
|
||||
'user:string'
|
||||
}
|
||||
|
||||
validate_server_section() {
|
||||
validate_common_server_options_ server "$1" "$2"
|
||||
}
|
||||
|
||||
validate_ss_local_section() {
|
||||
validate_common_client_options_ ss_local "$1" "$2" \
|
||||
'acl:file'
|
||||
}
|
||||
|
||||
validate_ss_redir_section() {
|
||||
validate_common_client_options_ ss_redir "$1" "$2"
|
||||
}
|
||||
|
||||
validate_ss_rules_section() {
|
||||
"${2:-ss_validate}" ss_rules "$1" \
|
||||
'disabled:bool:0' \
|
||||
'redir_tcp:uci("shadowsocks-libev", "@ss_redir")' \
|
||||
'redir_udp:uci("shadowsocks-libev", "@ss_redir")' \
|
||||
'src_ips_bypass:or(ipaddr,cidr)' \
|
||||
'src_ips_forward:or(ipaddr,cidr)' \
|
||||
'src_ips_checkdst:or(ipaddr,cidr)' \
|
||||
'dst_ips_bypass_file:file' \
|
||||
'dst_ips_bypass:or(ipaddr,cidr)' \
|
||||
'dst_ips_forward_file:file' \
|
||||
'dst_ips_forward:or(ipaddr,cidr)' \
|
||||
'src_default:or("bypass", "forward", "checkdst"):checkdst' \
|
||||
'dst_default:or("bypass", "forward"):bypass' \
|
||||
'local_default:or("bypass", "forward", "checkdst"):bypass' \
|
||||
'nft_tcp_extra:string' \
|
||||
'nft_udp_extra:string' \
|
||||
'ifnames:maxlength(15)'
|
||||
}
|
||||
|
||||
validate_ss_server_section() {
|
||||
validate_common_server_options_ ss_server "$1" \
|
||||
validate_common_options_ \
|
||||
"$2" \
|
||||
'local_address:ipaddr' \
|
||||
'local_ipv4_address:ip4addr' \
|
||||
'local_ipv6_address:ip6addr' \
|
||||
'bind_address:ipaddr' \
|
||||
'acl:file'
|
||||
}
|
||||
|
||||
validate_ss_tunnel_section() {
|
||||
validate_common_client_options_ ss_tunnel "$1" \
|
||||
"$2" \
|
||||
'tunnel_address:regex(".+\:[0-9]+")'
|
||||
}
|
122
shadowsocks-libev/files/ss-rules/chain.uc
Normal file
122
shadowsocks-libev/files/ss-rules/chain.uc
Normal file
@ -0,0 +1,122 @@
|
||||
{%
|
||||
function get_local_verdict() {
|
||||
let v = o_local_default;
|
||||
if (v == "checkdst") {
|
||||
return "goto ss_rules_dst_" + proto;
|
||||
} else if (v == "forward") {
|
||||
return "goto ss_rules_forward_" + proto;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function get_src_default_verdict() {
|
||||
let v = o_src_default;
|
||||
if (v == "checkdst") {
|
||||
return "goto ss_rules_dst_" + proto;
|
||||
} else if (v == "forward") {
|
||||
return "goto ss_rules_forward_" + proto;
|
||||
} else {
|
||||
return "accept";
|
||||
}
|
||||
}
|
||||
|
||||
function get_dst_default_verdict() {
|
||||
let v = o_dst_default;
|
||||
if (v == "forward") {
|
||||
return "goto ss_rules_forward_" + proto;
|
||||
} else {
|
||||
return "accept";
|
||||
}
|
||||
}
|
||||
|
||||
function get_ifnames() {
|
||||
let res = [];
|
||||
for (let ifname in split(o_ifnames, /[ \t\n]/)) {
|
||||
ifname = trim(ifname);
|
||||
if (ifname) push(res, ifname);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
let type, hook, priority, redir_port;
|
||||
if (proto == "tcp") {
|
||||
type = "nat";
|
||||
hook = "prerouting";
|
||||
priority = -1;
|
||||
redir_port = o_redir_tcp_port;
|
||||
} else if (proto == "udp") {
|
||||
type = "filter";
|
||||
hook = "prerouting";
|
||||
priority = "mangle";
|
||||
redir_port = o_redir_udp_port;
|
||||
if (system("
|
||||
set -o errexit
|
||||
iprr() {
|
||||
while ip $1 rule del fwmark 1 lookup 100 2>/dev/null; do true; done
|
||||
ip $1 rule add fwmark 1 lookup 100
|
||||
ip $1 route flush table 100 2>/dev/null || true
|
||||
ip $1 route add local default dev lo table 100
|
||||
}
|
||||
iprr -4
|
||||
iprr -6
|
||||
") != 0) {
|
||||
return ;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
%}
|
||||
{% if (redir_port): %}
|
||||
|
||||
chain ss_rules_pre_{{ proto }} {
|
||||
type {{ type }} hook {{ hook }} priority {{ priority }};
|
||||
meta l4proto {{ proto }}{%- let ifnames=get_ifnames(); if (length(ifnames)): %} iifname { {{join(", ", ifnames)}} }{% endif %} goto ss_rules_pre_src_{{ proto }};
|
||||
}
|
||||
|
||||
chain ss_rules_pre_src_{{ proto }} {
|
||||
ip daddr @ss_rules_dst_bypass_ accept;
|
||||
ip6 daddr @ss_rules6_dst_bypass_ accept;
|
||||
goto ss_rules_src_{{ proto }};
|
||||
}
|
||||
|
||||
chain ss_rules_src_{{ proto }} {
|
||||
ip saddr @ss_rules_src_bypass accept;
|
||||
ip saddr @ss_rules_src_forward goto ss_rules_forward_{{ proto }};
|
||||
ip saddr @ss_rules_src_checkdst goto ss_rules_dst_{{ proto }};
|
||||
ip6 saddr @ss_rules6_src_bypass accept;
|
||||
ip6 saddr @ss_rules6_src_forward goto ss_rules_forward_{{ proto }};
|
||||
ip6 saddr @ss_rules6_src_checkdst goto ss_rules_dst_{{ proto }};
|
||||
{{ get_src_default_verdict() }};
|
||||
}
|
||||
|
||||
chain ss_rules_dst_{{ proto }} {
|
||||
ip daddr @ss_rules_dst_bypass accept;
|
||||
ip daddr @ss_rules_dst_forward goto ss_rules_forward_{{ proto }};
|
||||
ip6 daddr @ss_rules6_dst_bypass accept;
|
||||
ip6 daddr @ss_rules6_dst_forward goto ss_rules_forward_{{ proto }};
|
||||
{{ get_dst_default_verdict() }};
|
||||
}
|
||||
|
||||
{% if (proto == "tcp"): %}
|
||||
chain ss_rules_forward_{{ proto }} {
|
||||
meta l4proto tcp {{ o_nft_tcp_extra }} redirect to :{{ redir_port }};
|
||||
}
|
||||
{% let local_verdict = get_local_verdict(); if (local_verdict): %}
|
||||
chain ss_rules_local_out {
|
||||
type {{ type }} hook output priority -1;
|
||||
meta l4proto != tcp accept;
|
||||
ip daddr @ss_rules_dst_bypass_ accept;
|
||||
ip daddr @ss_rules_dst_bypass accept;
|
||||
ip6 daddr @ss_rules6_dst_bypass_ accept;
|
||||
ip6 daddr @ss_rules6_dst_bypass accept;
|
||||
{{ local_verdict }};
|
||||
}
|
||||
{% endif %}
|
||||
{% elif (proto == "udp"): %}
|
||||
chain ss_rules_forward_{{ proto }} {
|
||||
meta l4proto udp {{ o_nft_udp_extra }} meta mark set 1 tproxy to :{{ redir_port }};
|
||||
}
|
||||
{% endif %}
|
||||
{% endif %}
|
114
shadowsocks-libev/files/ss-rules/set.uc
Normal file
114
shadowsocks-libev/files/ss-rules/set.uc
Normal file
@ -0,0 +1,114 @@
|
||||
{%
|
||||
let fs = require("fs");
|
||||
|
||||
let o_dst_bypass4_ = "
|
||||
0.0.0.0/8
|
||||
10.0.0.0/8
|
||||
100.64.0.0/10
|
||||
127.0.0.0/8
|
||||
169.254.0.0/16
|
||||
172.16.0.0/12
|
||||
192.0.0.0/24
|
||||
192.0.2.0/24
|
||||
192.31.196.0/24
|
||||
192.52.193.0/24
|
||||
192.88.99.0/24
|
||||
192.168.0.0/16
|
||||
192.175.48.0/24
|
||||
198.18.0.0/15
|
||||
198.51.100.0/24
|
||||
203.0.113.0/24
|
||||
224.0.0.0/4
|
||||
240.0.0.0/4
|
||||
";
|
||||
let o_dst_bypass6_ = "
|
||||
::1/128
|
||||
::/128
|
||||
::ffff:0:0/96
|
||||
64:ff9b:1::/48
|
||||
100::/64
|
||||
fe80::/10
|
||||
2001::/23
|
||||
fc00::/7
|
||||
";
|
||||
let o_dst_bypass_ = o_dst_bypass4_ + " " + o_dst_bypass6_;
|
||||
|
||||
let set_suffix = {
|
||||
"src_bypass": {
|
||||
str: o_src_bypass,
|
||||
},
|
||||
"src_forward": {
|
||||
str: o_src_forward,
|
||||
},
|
||||
"src_checkdst": {
|
||||
str: o_src_checkdst,
|
||||
},
|
||||
"dst_bypass": {
|
||||
str: o_dst_bypass,
|
||||
file: o_dst_bypass_file,
|
||||
},
|
||||
"dst_bypass_": {
|
||||
str: o_dst_bypass_,
|
||||
},
|
||||
"dst_forward": {
|
||||
str: o_dst_forward,
|
||||
file: o_dst_forward_file,
|
||||
},
|
||||
"dst_forward_rrst_": {},
|
||||
};
|
||||
|
||||
function set_name(suf, af) {
|
||||
if (af == 4) {
|
||||
return "ss_rules_"+suf;
|
||||
} else {
|
||||
return "ss_rules6_"+suf;
|
||||
}
|
||||
}
|
||||
|
||||
function set_elements_parse(res, str, af) {
|
||||
for (let addr in split(str, /[ \t\n]/)) {
|
||||
addr = trim(addr);
|
||||
if (!addr) continue;
|
||||
if (af == 4 && index(addr, ":") != -1) continue;
|
||||
if (af == 6 && index(addr, ":") == -1) continue;
|
||||
push(res, addr);
|
||||
}
|
||||
}
|
||||
|
||||
function set_elements(suf, af) {
|
||||
let obj = set_suffix[suf];
|
||||
let res = [];
|
||||
let addr;
|
||||
|
||||
let str = obj["str"];
|
||||
if (str) {
|
||||
set_elements_parse(res, str, af);
|
||||
}
|
||||
|
||||
let file = obj["file"];
|
||||
if (file) {
|
||||
let fd = fs.open(file);
|
||||
if (fd) {
|
||||
str = fd.read("all");
|
||||
set_elements_parse(res, str, af);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
%}
|
||||
|
||||
{% for (let suf in set_suffix): for (let af in [4, 6]): %}
|
||||
set {{ set_name(suf, af) }} {
|
||||
type ipv{{af}}_addr;
|
||||
flags interval;
|
||||
auto-merge;
|
||||
{% let elems = set_elements(suf, af); if (length(elems)): %}
|
||||
elements = {
|
||||
{% for (let i = 0; i < length(elems); i++): %}
|
||||
{{ elems[i] }}{% if (i < length(elems) - 1): %},{% endif %}{% print("\n") %}
|
||||
{% endfor %}
|
||||
}
|
||||
{% endif %}
|
||||
}
|
||||
{% endfor; endfor %}
|
8
shadowsocks-libev/files/ss-rules/ss-rules.uc
Normal file
8
shadowsocks-libev/files/ss-rules/ss-rules.uc
Normal file
@ -0,0 +1,8 @@
|
||||
{%
|
||||
|
||||
include("set.uc");
|
||||
include("chain.uc", {proto: "tcp"});
|
||||
include("chain.uc", {proto: "udp"});
|
||||
|
||||
%}
|
||||
|
85
shadowsocks-rust/Makefile
Normal file
85
shadowsocks-rust/Makefile
Normal file
@ -0,0 +1,85 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Copyright (C) 2017-2020 Yousong Zhou <yszhou4tech@gmail.com>
|
||||
# Copyright (C) 2021 ImmortalWrt.org
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=shadowsocks-rust
|
||||
PKG_VERSION:=1.15.2
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_HEADER:=shadowsocks-v$(PKG_VERSION)
|
||||
PKG_SOURCE_BODY:=unknown-linux-musl
|
||||
PKG_SOURCE_FOOTER:=tar.xz
|
||||
PKG_SOURCE_URL:=https://github.com/shadowsocks/shadowsocks-rust/releases/download/v$(PKG_VERSION)/
|
||||
|
||||
ifeq ($(ARCH),aarch64)
|
||||
PKG_SOURCE:=$(PKG_SOURCE_HEADER).aarch64-$(PKG_SOURCE_BODY).$(PKG_SOURCE_FOOTER)
|
||||
PKG_HASH:=97850893c5a35b68ccd419b542c1785e4c0006e8c0c0b10eac8e5b8c67b12704
|
||||
else ifeq ($(ARCH),arm)
|
||||
# Referred to golang/golang-values.mk
|
||||
ARM_CPU_FEATURES:=$(word 2,$(subst +,$(space),$(call qstrip,$(CONFIG_CPU_TYPE))))
|
||||
ifeq ($(ARM_CPU_FEATURES),)
|
||||
PKG_SOURCE:=$(PKG_SOURCE_HEADER).arm-$(PKG_SOURCE_BODY)eabi.$(PKG_SOURCE_FOOTER)
|
||||
PKG_HASH:=728f4550abe4f18679555fa00b88ce889d2f412be7fa0d96bf153d086ad0c63e
|
||||
else
|
||||
PKG_SOURCE:=$(PKG_SOURCE_HEADER).arm-$(PKG_SOURCE_BODY)eabihf.$(PKG_SOURCE_FOOTER)
|
||||
PKG_HASH:=f13ae6497843347c91ef8b0634cee96f5043a644b2fba30009cafd6c9e65d7df
|
||||
endif
|
||||
else ifeq ($(ARCH),i386)
|
||||
PKG_SOURCE:=$(PKG_SOURCE_HEADER).i686-$(PKG_SOURCE_BODY).$(PKG_SOURCE_FOOTER)
|
||||
PKG_HASH:=a8558a9e898f9ba875136c3d038e968ca8d301a7dcde977f6483d5072f57695f
|
||||
else ifeq ($(ARCH),mips)
|
||||
PKG_SOURCE:=$(PKG_SOURCE_HEADER).mips-$(PKG_SOURCE_BODY).$(PKG_SOURCE_FOOTER)
|
||||
PKG_HASH:=a3f99d549c9f417fef63fa323840e0c4fb4dc96a53cf8329293c2a4e485ed239
|
||||
else ifeq ($(ARCH),mipsel)
|
||||
PKG_SOURCE:=$(PKG_SOURCE_HEADER).mipsel-$(PKG_SOURCE_BODY).$(PKG_SOURCE_FOOTER)
|
||||
PKG_HASH:=47d0f10d94216376057fc4238ebab68d19e3882293d5fe76ac3d29c41458a985
|
||||
else ifeq ($(ARCH),x86_64)
|
||||
PKG_SOURCE:=$(PKG_SOURCE_HEADER).x86_64-$(PKG_SOURCE_BODY).$(PKG_SOURCE_FOOTER)
|
||||
PKG_HASH:=69c2df2bd4e9e2ff0d70faa14b70888de2eb205ab2a49dd7066c86363e2acc50
|
||||
# Set the default value to make OpenWrt Package Checker happy
|
||||
else
|
||||
PKG_SOURCE:=dummy
|
||||
PKG_HASH:=dummy
|
||||
endif
|
||||
|
||||
PKG_MAINTAINER:=Tianling Shen <cnsztl@immortalwrt.org>
|
||||
PKG_LICENSE:=MIT
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
TAR_CMD:=$(HOST_TAR) -C $(PKG_BUILD_DIR) $(TAR_OPTIONS)
|
||||
|
||||
define Package/shadowsocks-rust/Default
|
||||
define Package/shadowsocks-rust-$(1)
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=Web Servers/Proxies
|
||||
TITLE:=shadowsocks-rust $(1)
|
||||
URL:=https://github.com/shadowsocks/shadowsocks-rust
|
||||
DEPENDS:=@USE_MUSL @(aarch64||arm||i386||mips||mipsel||x86_64) @!(TARGET_x86_geode||TARGET_x86_legacy)
|
||||
endef
|
||||
|
||||
define Package/shadowsocks-rust-$(1)/install
|
||||
$$(INSTALL_DIR) $$(1)/usr/bin
|
||||
$$(INSTALL_BIN) $$(PKG_BUILD_DIR)/$(1) $$(1)/usr/bin
|
||||
endef
|
||||
endef
|
||||
|
||||
SHADOWSOCKS_COMPONENTS:=sslocal ssmanager ssserver ssurl ssservice
|
||||
define shadowsocks-rust/templates
|
||||
$(foreach component,$(SHADOWSOCKS_COMPONENTS),
|
||||
$(call Package/shadowsocks-rust/Default,$(component))
|
||||
)
|
||||
endef
|
||||
$(eval $(call shadowsocks-rust/templates))
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
$(foreach component,$(SHADOWSOCKS_COMPONENTS), \
|
||||
$(eval $(call BuildPackage,shadowsocks-rust-$(component))) \
|
||||
)
|
64
shadowsocksr-libev/Makefile
Normal file
64
shadowsocksr-libev/Makefile
Normal file
@ -0,0 +1,64 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Copyright (C) 2017-2020 Yousong Zhou <yszhou4tech@gmail.com>
|
||||
# Copyright (C) 2018 Lean <coolsnowwolf@gmail.com>
|
||||
# Copyright (C) 2021 ImmortalWrt.org
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=shadowsocksr-libev
|
||||
PKG_VERSION:=2.5.6
|
||||
PKG_RELEASE:=9
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/shadowsocksrr/shadowsocksr-libev
|
||||
PKG_SOURCE_DATE:=2018-03-07
|
||||
PKG_SOURCE_VERSION:=d63ff863800a5645aca4309d5dd5962bd1e95543
|
||||
PKG_MIRROR_HASH:=34308ed827a5dd4f4e35619914102d55b00604faa44fda051d1d25fb4a319325
|
||||
|
||||
PKG_LICENSE:=GPL-3.0
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
||||
PKG_FIXUP:=autoreconf
|
||||
PKG_USE_MIPS16:=0
|
||||
PKG_BUILD_PARALLEL:=1
|
||||
PKG_INSTALL:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/shadowsocksr-libev/Default
|
||||
define Package/shadowsocksr-libev-ssr-$(1)
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
SUBMENU:=Web Servers/Proxies
|
||||
TITLE:=shadowsocksr-libev ssr-$(1)
|
||||
URL:=https://github.com/shadowsocksrr/shadowsocksr-libev
|
||||
DEPENDS:=+libev +libsodium +libopenssl +libpthread +libpcre +libudns +zlib
|
||||
endef
|
||||
|
||||
define Package/shadowsocksr-libev-ssr-$(1)/install
|
||||
$$(INSTALL_DIR) $$(1)/usr/bin
|
||||
$$(INSTALL_BIN) $$(PKG_INSTALL_DIR)/usr/bin/ss-$(1) $$(1)/usr/bin/ssr-$(1)
|
||||
endef
|
||||
endef
|
||||
|
||||
SHADOWSOCKSR_COMPONENTS:=check local nat redir server
|
||||
define shadowsocksr-libev/templates
|
||||
$(foreach component,$(SHADOWSOCKSR_COMPONENTS),
|
||||
$(call Package/shadowsocksr-libev/Default,$(component))
|
||||
)
|
||||
endef
|
||||
$(eval $(call shadowsocksr-libev/templates))
|
||||
|
||||
CONFIGURE_ARGS += \
|
||||
--disable-documentation \
|
||||
--disable-ssp \
|
||||
--disable-assert \
|
||||
--enable-system-shared-lib
|
||||
|
||||
TARGET_CFLAGS += -flto
|
||||
TARGET_LDFLAGS += -Wl,--gc-sections,--as-needed
|
||||
|
||||
$(foreach component,$(SHADOWSOCKSR_COMPONENTS), \
|
||||
$(eval $(call BuildPackage,shadowsocksr-libev-ssr-$(component))) \
|
||||
)
|
397
shadowsocksr-libev/patches/0001-Add-ss-server-and-ss-check.patch
Normal file
397
shadowsocksr-libev/patches/0001-Add-ss-server-and-ss-check.patch
Normal file
@ -0,0 +1,397 @@
|
||||
--- a/.gitignore
|
||||
+++ b/.gitignore
|
||||
@@ -2,6 +2,7 @@ build/
|
||||
.deps/
|
||||
/Makefile
|
||||
src/Makefile
|
||||
+server/Makefile
|
||||
libev/Makefile
|
||||
libudns/Makefile
|
||||
libcork/Makefile
|
||||
--- a/Makefile.am
|
||||
+++ b/Makefile.am
|
||||
@@ -1,7 +1,7 @@
|
||||
if USE_SYSTEM_SHARED_LIB
|
||||
-SUBDIRS = libcork libipset src
|
||||
+SUBDIRS = libcork libipset src server
|
||||
else
|
||||
-SUBDIRS = libsodium libcork libipset libudns libev src
|
||||
+SUBDIRS = libsodium libcork libipset libudns libev src server
|
||||
endif
|
||||
|
||||
if ENABLE_DOCUMENTATION
|
||||
--- a/Makefile.in
|
||||
+++ b/Makefile.in
|
||||
@@ -195,7 +195,7 @@ am__define_uniq_tagged_files = \
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
CSCOPE = cscope
|
||||
-DIST_SUBDIRS = libsodium libcork libipset libudns libev src doc
|
||||
+DIST_SUBDIRS = libsodium libcork libipset libudns libev src server doc
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \
|
||||
$(srcdir)/shadowsocks-libev.pc.in $(top_srcdir)/auto/ar-lib \
|
||||
$(top_srcdir)/auto/compile $(top_srcdir)/auto/config.guess \
|
||||
@@ -377,8 +377,9 @@ top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@SUBDIRS = libsodium libcork libipset \
|
||||
-@USE_SYSTEM_SHARED_LIB_FALSE@ libudns libev src $(am__append_1)
|
||||
-@USE_SYSTEM_SHARED_LIB_TRUE@SUBDIRS = libcork libipset src \
|
||||
+@USE_SYSTEM_SHARED_LIB_FALSE@ libudns libev src server \
|
||||
+@USE_SYSTEM_SHARED_LIB_FALSE@ $(am__append_1)
|
||||
+@USE_SYSTEM_SHARED_LIB_TRUE@SUBDIRS = libcork libipset src server \
|
||||
@USE_SYSTEM_SHARED_LIB_TRUE@ $(am__append_1)
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
pkgconfiglibdir = $(libdir)/pkgconfig
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -649,7 +649,6 @@ PTHREAD_CC
|
||||
ax_pthread_config
|
||||
INET_NTOP_LIB
|
||||
MV
|
||||
-RM
|
||||
GZIP
|
||||
XMLTO
|
||||
ASCIIDOC
|
||||
@@ -757,6 +756,7 @@ infodir
|
||||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
+runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
@@ -857,6 +857,7 @@ datadir='${datarootdir}'
|
||||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
+runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||
@@ -1109,6 +1110,15 @@ do
|
||||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
+ | --runstate | --runstat | --runsta | --runst | --runs \
|
||||
+ | --run | --ru | --r)
|
||||
+ ac_prev=runstatedir ;;
|
||||
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
+ | --run=* | --ru=* | --r=*)
|
||||
+ runstatedir=$ac_optarg ;;
|
||||
+
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
@@ -1246,7 +1256,7 @@ fi
|
||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
- libdir localedir mandir
|
||||
+ libdir localedir mandir runstatedir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
@@ -1399,6 +1409,7 @@ Fine tuning of the installation director
|
||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
@@ -2472,8 +2483,8 @@ ac_configure="$SHELL $ac_aux_dir/configu
|
||||
|
||||
|
||||
|
||||
-# expand $ac_aux_dir to an absolute path
|
||||
-am_aux_dir=`cd $ac_aux_dir && pwd`
|
||||
+# Expand $ac_aux_dir to an absolute path.
|
||||
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
|
||||
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
@@ -3783,7 +3794,7 @@ $as_echo "$ac_cv_safe_to_define___extens
|
||||
|
||||
|
||||
|
||||
-am__api_version='1.14'
|
||||
+am__api_version='1.15'
|
||||
|
||||
# Find a good install program. We prefer a C program (faster),
|
||||
# so one script is as good as another. But avoid the broken or
|
||||
@@ -3972,7 +3983,7 @@ else
|
||||
$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
|
||||
fi
|
||||
|
||||
-if test x"${install_sh}" != xset; then
|
||||
+if test x"${install_sh+set}" != xset; then
|
||||
case $am_aux_dir in
|
||||
*\ * | *\ *)
|
||||
install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
|
||||
@@ -4363,8 +4374,8 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}ma
|
||||
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
|
||||
mkdir_p='$(MKDIR_P)'
|
||||
|
||||
-# We need awk for the "check" target. The system "awk" is bad on
|
||||
-# some platforms.
|
||||
+# We need awk for the "check" target (and possibly the TAP driver). The
|
||||
+# system "awk" is bad on some platforms.
|
||||
# Always define AMTAR for backward compatibility. Yes, it's still used
|
||||
# in the wild :-( We should find a proper way to deprecate it ...
|
||||
AMTAR='$${TAR-tar}'
|
||||
@@ -4549,6 +4560,7 @@ END
|
||||
as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
|
||||
fi
|
||||
fi
|
||||
+
|
||||
if test -n "$ac_tool_prefix"; then
|
||||
for ac_prog in ar lib "link -lib"
|
||||
do
|
||||
@@ -12494,47 +12506,6 @@ $as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
- # Extract the first word of "rm", so it can be a program name with args.
|
||||
-set dummy rm; ac_word=$2
|
||||
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
-$as_echo_n "checking for $ac_word... " >&6; }
|
||||
-if ${ac_cv_path_RM+:} false; then :
|
||||
- $as_echo_n "(cached) " >&6
|
||||
-else
|
||||
- case $RM in
|
||||
- [\\/]* | ?:[\\/]*)
|
||||
- ac_cv_path_RM="$RM" # Let the user override the test with a path.
|
||||
- ;;
|
||||
- *)
|
||||
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
-for as_dir in $PATH
|
||||
-do
|
||||
- IFS=$as_save_IFS
|
||||
- test -z "$as_dir" && as_dir=.
|
||||
- for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
|
||||
- ac_cv_path_RM="$as_dir/$ac_word$ac_exec_ext"
|
||||
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
- break 2
|
||||
- fi
|
||||
-done
|
||||
- done
|
||||
-IFS=$as_save_IFS
|
||||
-
|
||||
- test -z "$ac_cv_path_RM" && ac_cv_path_RM="rm"
|
||||
- ;;
|
||||
-esac
|
||||
-fi
|
||||
-RM=$ac_cv_path_RM
|
||||
-if test -n "$RM"; then
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RM" >&5
|
||||
-$as_echo "$RM" >&6; }
|
||||
-else
|
||||
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
-$as_echo "no" >&6; }
|
||||
-fi
|
||||
-
|
||||
-
|
||||
# Extract the first word of "mv", so it can be a program name with args.
|
||||
set dummy mv; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
@@ -16204,15 +16175,162 @@ $as_echo "#define HAVE_IPv6 1" >>confdef
|
||||
|
||||
|
||||
if test -z "$USE_SYSTEM_SHARED_LIB_TRUE"; then :
|
||||
- else
|
||||
+
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sodium_init in -lsodium" >&5
|
||||
+$as_echo_n "checking for sodium_init in -lsodium... " >&6; }
|
||||
+if ${ac_cv_lib_sodium_sodium_init+:} false; then :
|
||||
+ $as_echo_n "(cached) " >&6
|
||||
+else
|
||||
+ ac_check_lib_save_LIBS=$LIBS
|
||||
+LIBS="-lsodium $LIBS"
|
||||
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+
|
||||
+/* Override any GCC internal prototype to avoid an error.
|
||||
+ Use char because int might match the return type of a GCC
|
||||
+ builtin and then its argument prototype would still apply. */
|
||||
+#ifdef __cplusplus
|
||||
+extern "C"
|
||||
+#endif
|
||||
+char sodium_init ();
|
||||
+int
|
||||
+main ()
|
||||
+{
|
||||
+return sodium_init ();
|
||||
+ ;
|
||||
+ return 0;
|
||||
+}
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_link "$LINENO"; then :
|
||||
+ ac_cv_lib_sodium_sodium_init=yes
|
||||
+else
|
||||
+ ac_cv_lib_sodium_sodium_init=no
|
||||
+fi
|
||||
+rm -f core conftest.err conftest.$ac_objext \
|
||||
+ conftest$ac_exeext conftest.$ac_ext
|
||||
+LIBS=$ac_check_lib_save_LIBS
|
||||
+fi
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sodium_sodium_init" >&5
|
||||
+$as_echo "$ac_cv_lib_sodium_sodium_init" >&6; }
|
||||
+if test "x$ac_cv_lib_sodium_sodium_init" = xyes; then :
|
||||
+ cat >>confdefs.h <<_ACEOF
|
||||
+#define HAVE_LIBSODIUM 1
|
||||
+_ACEOF
|
||||
+
|
||||
+ LIBS="-lsodium $LIBS"
|
||||
+
|
||||
+else
|
||||
+
|
||||
+ as_fn_error $? "Couldn't find libsodium. Try installing libsodium-dev[el]." "$LINENO" 5
|
||||
+
|
||||
+fi
|
||||
+
|
||||
+
|
||||
+else
|
||||
subdirs="$subdirs libsodium"
|
||||
|
||||
fi
|
||||
|
||||
-ac_config_files="$ac_config_files shadowsocks-libev.pc Makefile libcork/Makefile libipset/Makefile src/Makefile"
|
||||
+ac_config_files="$ac_config_files shadowsocks-libev.pc Makefile libcork/Makefile libipset/Makefile src/Makefile server/Makefile"
|
||||
|
||||
if test -z "$USE_SYSTEM_SHARED_LIB_TRUE"; then :
|
||||
- else
|
||||
+
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dns_dnlen in -ludns" >&5
|
||||
+$as_echo_n "checking for dns_dnlen in -ludns... " >&6; }
|
||||
+if ${ac_cv_lib_udns_dns_dnlen+:} false; then :
|
||||
+ $as_echo_n "(cached) " >&6
|
||||
+else
|
||||
+ ac_check_lib_save_LIBS=$LIBS
|
||||
+LIBS="-ludns $LIBS"
|
||||
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+
|
||||
+/* Override any GCC internal prototype to avoid an error.
|
||||
+ Use char because int might match the return type of a GCC
|
||||
+ builtin and then its argument prototype would still apply. */
|
||||
+#ifdef __cplusplus
|
||||
+extern "C"
|
||||
+#endif
|
||||
+char dns_dnlen ();
|
||||
+int
|
||||
+main ()
|
||||
+{
|
||||
+return dns_dnlen ();
|
||||
+ ;
|
||||
+ return 0;
|
||||
+}
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_link "$LINENO"; then :
|
||||
+ ac_cv_lib_udns_dns_dnlen=yes
|
||||
+else
|
||||
+ ac_cv_lib_udns_dns_dnlen=no
|
||||
+fi
|
||||
+rm -f core conftest.err conftest.$ac_objext \
|
||||
+ conftest$ac_exeext conftest.$ac_ext
|
||||
+LIBS=$ac_check_lib_save_LIBS
|
||||
+fi
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_udns_dns_dnlen" >&5
|
||||
+$as_echo "$ac_cv_lib_udns_dns_dnlen" >&6; }
|
||||
+if test "x$ac_cv_lib_udns_dns_dnlen" = xyes; then :
|
||||
+ cat >>confdefs.h <<_ACEOF
|
||||
+#define HAVE_LIBUDNS 1
|
||||
+_ACEOF
|
||||
+
|
||||
+ LIBS="-ludns $LIBS"
|
||||
+
|
||||
+else
|
||||
+ as_fn_error $? "Couldn't find libudns. Try installing libudns-dev or udns-devel." "$LINENO" 5
|
||||
+fi
|
||||
+
|
||||
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ev_loop_destroy in -lev" >&5
|
||||
+$as_echo_n "checking for ev_loop_destroy in -lev... " >&6; }
|
||||
+if ${ac_cv_lib_ev_ev_loop_destroy+:} false; then :
|
||||
+ $as_echo_n "(cached) " >&6
|
||||
+else
|
||||
+ ac_check_lib_save_LIBS=$LIBS
|
||||
+LIBS="-lev $LIBS"
|
||||
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
+/* end confdefs.h. */
|
||||
+
|
||||
+/* Override any GCC internal prototype to avoid an error.
|
||||
+ Use char because int might match the return type of a GCC
|
||||
+ builtin and then its argument prototype would still apply. */
|
||||
+#ifdef __cplusplus
|
||||
+extern "C"
|
||||
+#endif
|
||||
+char ev_loop_destroy ();
|
||||
+int
|
||||
+main ()
|
||||
+{
|
||||
+return ev_loop_destroy ();
|
||||
+ ;
|
||||
+ return 0;
|
||||
+}
|
||||
+_ACEOF
|
||||
+if ac_fn_c_try_link "$LINENO"; then :
|
||||
+ ac_cv_lib_ev_ev_loop_destroy=yes
|
||||
+else
|
||||
+ ac_cv_lib_ev_ev_loop_destroy=no
|
||||
+fi
|
||||
+rm -f core conftest.err conftest.$ac_objext \
|
||||
+ conftest$ac_exeext conftest.$ac_ext
|
||||
+LIBS=$ac_check_lib_save_LIBS
|
||||
+fi
|
||||
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ev_ev_loop_destroy" >&5
|
||||
+$as_echo "$ac_cv_lib_ev_ev_loop_destroy" >&6; }
|
||||
+if test "x$ac_cv_lib_ev_ev_loop_destroy" = xyes; then :
|
||||
+ cat >>confdefs.h <<_ACEOF
|
||||
+#define HAVE_LIBEV 1
|
||||
+_ACEOF
|
||||
+
|
||||
+ LIBS="-lev $LIBS"
|
||||
+
|
||||
+else
|
||||
+ as_fn_error $? "Couldn't find libev. Try installing libev-dev[el]." "$LINENO" 5
|
||||
+fi
|
||||
+
|
||||
+
|
||||
+else
|
||||
ac_config_files="$ac_config_files libudns/Makefile libev/Makefile"
|
||||
|
||||
fi
|
||||
@@ -17258,6 +17376,7 @@ do
|
||||
"libcork/Makefile") CONFIG_FILES="$CONFIG_FILES libcork/Makefile" ;;
|
||||
"libipset/Makefile") CONFIG_FILES="$CONFIG_FILES libipset/Makefile" ;;
|
||||
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
|
||||
+ "server/Makefile") CONFIG_FILES="$CONFIG_FILES server/Makefile" ;;
|
||||
"libudns/Makefile") CONFIG_FILES="$CONFIG_FILES libudns/Makefile" ;;
|
||||
"libev/Makefile") CONFIG_FILES="$CONFIG_FILES libev/Makefile" ;;
|
||||
"doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
|
||||
@@ -17958,8 +18077,8 @@ $as_echo X"$file" |
|
||||
fi
|
||||
|
||||
cfgfile="${ofile}T"
|
||||
- trap "$RM -f \"$cfgfile\"; exit 1" 1 2 15
|
||||
- $RM -f "$cfgfile"
|
||||
+ trap "$RM \"$cfgfile\"; exit 1" 1 2 15
|
||||
+ $RM "$cfgfile"
|
||||
|
||||
cat <<_LT_EOF >> "$cfgfile"
|
||||
#! $SHELL
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -315,7 +315,8 @@ AC_CONFIG_FILES([ shadowsocks-libev.pc
|
||||
Makefile
|
||||
libcork/Makefile
|
||||
libipset/Makefile
|
||||
- src/Makefile])
|
||||
+ src/Makefile
|
||||
+ server/Makefile])
|
||||
AM_COND_IF([USE_SYSTEM_SHARED_LIB],[
|
||||
AC_CHECK_LIB([udns], [dns_dnlen], ,[AC_MSG_ERROR([Couldn't find libudns. Try installing libudns-dev or udns-devel.])])
|
||||
AC_CHECK_LIB([ev], [ev_loop_destroy], ,[AC_MSG_ERROR([Couldn't find libev. Try installing libev-dev@<:@el@:>@.])])
|
@ -0,0 +1,20 @@
|
||||
--- a/src/obfs/obfs.c
|
||||
+++ b/src/obfs/obfs.c
|
||||
@@ -88,7 +88,7 @@ obfs_class *new_obfs_class(const char *p
|
||||
plugin->client_decode = tls12_ticket_auth_client_decode;
|
||||
|
||||
return plugin;
|
||||
- /*} else if (strcmp(plugin_name, "verify_simple") == 0) {
|
||||
+ } else if (strcmp(plugin_name, "verify_simple") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs_class));
|
||||
plugin->init_data = init_data;
|
||||
plugin->new_obfs = verify_simple_new_obfs;
|
||||
@@ -115,7 +115,7 @@ obfs_class *new_obfs_class(const char *p
|
||||
plugin->client_udp_pre_encrypt = NULL;
|
||||
plugin->client_udp_post_decrypt = NULL;
|
||||
|
||||
- return plugin;*/
|
||||
+ return plugin;
|
||||
} else if (strcmp(plugin_name, "auth_sha1") == 0) {
|
||||
obfs_class *plugin = (obfs_class *) malloc(sizeof(obfs_class));
|
||||
plugin->init_data = auth_simple_init_data;
|
37
shadowsocksr-libev/patches/0003-Refine-Usage.patch
Normal file
37
shadowsocksr-libev/patches/0003-Refine-Usage.patch
Normal file
@ -0,0 +1,37 @@
|
||||
--- a/src/utils.c
|
||||
+++ b/src/utils.c
|
||||
@@ -258,8 +258,6 @@ usage()
|
||||
{
|
||||
printf("\n");
|
||||
printf("shadowsocks-libev %s with %s\n\n", VERSION, USING_CRYPTO);
|
||||
- printf(
|
||||
- " maintained by Max Lv <max.c.lv@gmail.com> and Linus Yang <laokongzi@gmail.com>\n\n");
|
||||
printf(" usage:\n\n");
|
||||
#ifdef MODULE_LOCAL
|
||||
printf(" ss-local\n");
|
||||
@@ -299,6 +297,25 @@ usage()
|
||||
" The default cipher is rc4-md5.\n");
|
||||
printf("\n");
|
||||
printf(
|
||||
+ " -o <obfs> Obfs of your remote server: plain,\n");
|
||||
+ printf(
|
||||
+ " http_simple, http_post and tls1.2_ticket_auth.\n");
|
||||
+ printf(
|
||||
+ " -g <obfs-param> Obfs-Param of your remote server.\n");
|
||||
+ printf(
|
||||
+ " -O <protocol> Protocol of your remote server: origin,\n");
|
||||
+ printf(
|
||||
+ " auth_sha1, auth_sha1_v2, auth_sha1_v4,\n");
|
||||
+ printf(
|
||||
+ " auth_aes128_md5, auth_aes128_sha1,\n");
|
||||
+ printf(
|
||||
+ " auth_chain_a, auth_chain_b, auth_chain_c,\n");
|
||||
+ printf(
|
||||
+ " auth_chain_d, auth_chain_e and auth_chain_f.\n");
|
||||
+ printf(
|
||||
+ " -G <protocol-param> Protocol-Param of your remote server.\n");
|
||||
+ printf("\n");
|
||||
+ printf(
|
||||
" [-a <user>] Run as another user.\n");
|
||||
printf(
|
||||
" [-f <pid_file>] The file path to store pid.\n");
|
20
shadowsocksr-libev/patches/100-fix-gcc-10.patch
Normal file
20
shadowsocksr-libev/patches/100-fix-gcc-10.patch
Normal file
@ -0,0 +1,20 @@
|
||||
--- a/src/http.h
|
||||
+++ b/src/http.h
|
||||
@@ -29,6 +29,6 @@
|
||||
#include <stdio.h>
|
||||
#include "protocol.h"
|
||||
|
||||
-const protocol_t *const http_protocol;
|
||||
+extern const protocol_t *const http_protocol;
|
||||
|
||||
#endif
|
||||
--- a/src/tls.h
|
||||
+++ b/src/tls.h
|
||||
@@ -28,6 +28,6 @@
|
||||
|
||||
#include "protocol.h"
|
||||
|
||||
-const protocol_t *const tls_protocol;
|
||||
+extern const protocol_t *const tls_protocol;
|
||||
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
--- a/src/local.c
|
||||
+++ b/src/local.c
|
||||
@@ -718,7 +718,7 @@ server_recv_cb(EV_P_ ev_io *w, int reven
|
||||
|
||||
ss_free(hostname);
|
||||
} else {
|
||||
- strncpy(host, ip, sizeof(ip));
|
||||
+ strncpy(host, ip, INET6_ADDRSTRLEN);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
--- a/src/jconf.c
|
||||
+++ b/src/jconf.c
|
||||
@@ -259,6 +259,19 @@ read_jconf(const char *file)
|
||||
conf.server_legacy.obfs = to_string(value);
|
||||
} else if (strcmp(name, "obfs_param") == 0) { // SSR
|
||||
conf.server_legacy.obfs_param = to_string(value);
|
||||
+ } else if (strcmp(name, "mode") == 0) {
|
||||
+ char *mode_str = to_string(value);
|
||||
+
|
||||
+ if (strcmp(mode_str, "tcp_only") == 0)
|
||||
+ conf.mode = TCP_ONLY;
|
||||
+ else if (strcmp(mode_str, "tcp_and_udp") == 0)
|
||||
+ conf.mode = TCP_AND_UDP;
|
||||
+ else if (strcmp(mode_str, "udp_only") == 0)
|
||||
+ conf.mode = UDP_ONLY;
|
||||
+ else
|
||||
+ LOGI("ignore unknown mode: %s, use tcp_only as fallback",
|
||||
+ mode_str);
|
||||
+ ss_free(mode_str);
|
||||
} else {
|
||||
match = 0;
|
||||
}
|
||||
--- a/src/redir.c
|
||||
+++ b/src/redir.c
|
||||
@@ -1252,6 +1252,9 @@ main(int argc, char **argv)
|
||||
if (user == NULL) {
|
||||
user = conf->user;
|
||||
}
|
||||
+ if (mode == TCP_ONLY) {
|
||||
+ mode = conf->mode;
|
||||
+ }
|
||||
if (mtu == 0) {
|
||||
mtu = conf->mtu;
|
||||
}
|
@ -0,0 +1,154 @@
|
||||
--- a/completions/bash/ss-redir
|
||||
+++ b/completions/bash/ss-redir
|
||||
@@ -2,7 +2,7 @@ _ss_redir()
|
||||
{
|
||||
local cur prev opts ciphers
|
||||
ciphers='rc4-md5 table rc4 aes-128-cfb aes-192-cfb aes-256-cfb aes-128-ctr aes-192-ctr aes-256-ctr bf-cfb camellia-128-cfb camellia-192-cfb camellia-256-cfb cast5-cfb des-cfb idea-cfb rc2-cfb seed-cfb salsa20 chacha20 and chacha20-ietf'
|
||||
- opts='-s -b -p -k -f -t -m -c -a -n -u -U -v -h -A --mtu --help --mptcp -l'
|
||||
+ opts='-s -b -p -k -f -t -m -c -a -n -u -U -T -v -h -A --mtu --help --mptcp -l'
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
case "$prev" in
|
||||
--- a/src/jconf.c
|
||||
+++ b/src/jconf.c
|
||||
@@ -338,7 +338,11 @@ read_jconf(const char *file)
|
||||
check_json_value_type(value, json_boolean,
|
||||
"invalid config file: option 'ipv6_first' must be a boolean");
|
||||
conf.ipv6_first = value->u.boolean;
|
||||
- }
|
||||
+ } else if (strcmp(name, "tcp_tproxy") == 0) {
|
||||
+ check_json_value_type(value, json_boolean,
|
||||
+ "invalid config file: option 'tcp_tproxy' must be a boolean");
|
||||
+ conf.tcp_tproxy = value->u.boolean;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
--- a/src/jconf.h
|
||||
+++ b/src/jconf.h
|
||||
@@ -105,6 +105,7 @@ typedef struct {
|
||||
int mtu;
|
||||
int mptcp;
|
||||
int ipv6_first;
|
||||
+ int tcp_tproxy;
|
||||
} jconf_t;
|
||||
|
||||
jconf_t *read_jconf(const char *file);
|
||||
--- a/src/redir.c
|
||||
+++ b/src/redir.c
|
||||
@@ -71,6 +71,14 @@
|
||||
#define IP6T_SO_ORIGINAL_DST 80
|
||||
#endif
|
||||
|
||||
+#ifndef IP_TRANSPARENT
|
||||
+#define IP_TRANSPARENT 19
|
||||
+#endif
|
||||
+
|
||||
+#ifndef IPV6_TRANSPARENT
|
||||
+#define IPV6_TRANSPARENT 75
|
||||
+#endif
|
||||
+
|
||||
#include "includeobfs.h" // I don't want to modify makefile
|
||||
#include "jconf.h"
|
||||
|
||||
@@ -101,18 +109,28 @@ static struct cork_dllist inactive_profi
|
||||
static listen_ctx_t *current_profile;
|
||||
static struct cork_dllist all_connections;
|
||||
|
||||
+static int tcp_tproxy = 0; /* use tproxy instead of redirect (for tcp) */
|
||||
+
|
||||
int
|
||||
getdestaddr(int fd, struct sockaddr_storage *destaddr)
|
||||
{
|
||||
socklen_t socklen = sizeof(*destaddr);
|
||||
int error = 0;
|
||||
|
||||
- error = getsockopt(fd, SOL_IPV6, IP6T_SO_ORIGINAL_DST, destaddr, &socklen);
|
||||
- if (error) { // Didn't find a proper way to detect IP version.
|
||||
- error = getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, destaddr, &socklen);
|
||||
- if (error) {
|
||||
- return -1;
|
||||
- }
|
||||
+ if (tcp_tproxy) {
|
||||
+ error = getsockname(fd, (void *)destaddr, &socklen);
|
||||
+ } else {
|
||||
+ error = getsockopt(fd, SOL_IPV6, IP6T_SO_ORIGINAL_DST, destaddr, &socklen);
|
||||
+ if (error) { // Didn't find a proper way to detect IP version.
|
||||
+ error = getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, destaddr, &socklen);
|
||||
+ if (error) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (error) {
|
||||
+ return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -164,6 +182,23 @@ create_and_bind(const char *addr, const
|
||||
if (err == 0) {
|
||||
LOGI("tcp port reuse enabled");
|
||||
}
|
||||
+
|
||||
+ if (tcp_tproxy) {
|
||||
+ int level = 0, optname = 0;
|
||||
+ if (rp->ai_family == AF_INET) {
|
||||
+ level = IPPROTO_IP;
|
||||
+ optname = IP_TRANSPARENT;
|
||||
+ } else {
|
||||
+ level = IPPROTO_IPV6;
|
||||
+ optname = IPV6_TRANSPARENT;
|
||||
+ }
|
||||
+
|
||||
+ if (setsockopt(listen_sock, level, optname, &opt, sizeof(opt)) != 0) {
|
||||
+ ERROR("setsockopt IP_TRANSPARENT");
|
||||
+ exit(EXIT_FAILURE);
|
||||
+ }
|
||||
+ LOGI("tcp tproxy mode enabled");
|
||||
+ }
|
||||
|
||||
s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
|
||||
if (s == 0) {
|
||||
@@ -1094,7 +1129,7 @@ main(int argc, char **argv)
|
||||
|
||||
USE_TTY();
|
||||
|
||||
- while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUvA6"
|
||||
+ while ((c = getopt_long(argc, argv, "f:s:p:l:k:t:m:c:b:a:n:huUTvA6"
|
||||
"O:o:G:g:",
|
||||
long_options, &option_index)) != -1) {
|
||||
switch (c) {
|
||||
@@ -1169,6 +1204,9 @@ main(int argc, char **argv)
|
||||
case 'U':
|
||||
mode = UDP_ONLY;
|
||||
break;
|
||||
+ case 'T':
|
||||
+ tcp_tproxy = 1;
|
||||
+ break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
@@ -1255,6 +1293,9 @@ main(int argc, char **argv)
|
||||
if (mode == TCP_ONLY) {
|
||||
mode = conf->mode;
|
||||
}
|
||||
+ if (tcp_tproxy == 0) {
|
||||
+ tcp_tproxy = conf->tcp_tproxy;
|
||||
+ }
|
||||
if (mtu == 0) {
|
||||
mtu = conf->mtu;
|
||||
}
|
||||
--- a/src/utils.c
|
||||
+++ b/src/utils.c
|
||||
@@ -342,6 +342,10 @@ usage()
|
||||
#endif
|
||||
printf(
|
||||
" [-U] Enable UDP relay and disable TCP relay.\n");
|
||||
+#ifdef MODULE_REDIR
|
||||
+ printf(
|
||||
+ " [-T] Use tproxy instead of redirect (for tcp).\n");
|
||||
+#endif
|
||||
#ifdef MODULE_REMOTE
|
||||
printf(
|
||||
" [-6] Resovle hostname to IPv6 address first.\n");
|
55
shadowsocksr-libev/src/server/Makefile.am
Normal file
55
shadowsocksr-libev/src/server/Makefile.am
Normal file
@ -0,0 +1,55 @@
|
||||
VERSION_INFO = 2:0:0
|
||||
|
||||
AM_CFLAGS = -g -O2 -Wall -Werror -Wno-deprecated-declarations -fno-strict-aliasing -std=gnu99 -D_GNU_SOURCE
|
||||
AM_CFLAGS += $(PTHREAD_CFLAGS)
|
||||
if !USE_SYSTEM_SHARED_LIB
|
||||
AM_CFLAGS += -I$(top_srcdir)/libev
|
||||
AM_CFLAGS += -I$(top_srcdir)/libudns
|
||||
AM_CFLAGS += -I$(top_srcdir)/libsodium/src/libsodium/include
|
||||
endif
|
||||
AM_CFLAGS += -I$(top_srcdir)/libipset/include
|
||||
AM_CFLAGS += -I$(top_srcdir)/libcork/include
|
||||
AM_CFLAGS += $(LIBPCRE_CFLAGS)
|
||||
|
||||
SS_COMMON_LIBS = $(top_builddir)/libipset/libipset.la \
|
||||
$(top_builddir)/libcork/libcork.la \
|
||||
$(INET_NTOP_LIB) $(LIBPCRE_LIBS)
|
||||
if USE_SYSTEM_SHARED_LIB
|
||||
SS_COMMON_LIBS += -lev -lsodium -lm
|
||||
else
|
||||
SS_COMMON_LIBS += $(top_builddir)/libev/libev.la \
|
||||
$(top_builddir)/libsodium/src/libsodium/libsodium.la
|
||||
endif
|
||||
|
||||
bin_PROGRAMS = ss-server ss-check
|
||||
|
||||
sni_src = http.c \
|
||||
tls.c \
|
||||
rule.c
|
||||
|
||||
ss_check_SOURCES = check.c
|
||||
|
||||
ss_server_SOURCES = utils.c \
|
||||
netutils.c \
|
||||
jconf.c \
|
||||
json.c \
|
||||
encrypt.c \
|
||||
udprelay.c \
|
||||
cache.c \
|
||||
acl.c \
|
||||
resolv.c \
|
||||
server.c \
|
||||
$(sni_src)
|
||||
|
||||
|
||||
ss_check_LDADD = $(SS_COMMON_LIBS)
|
||||
ss_server_LDADD = $(SS_COMMON_LIBS)
|
||||
|
||||
if USE_SYSTEM_SHARED_LIB
|
||||
ss_server_LDADD += -ludns
|
||||
else
|
||||
ss_server_LDADD += $(top_builddir)/libudns/libudns.la
|
||||
endif
|
||||
|
||||
ss_check_CFLAGS = $(AM_CFLAGS)
|
||||
ss_server_CFLAGS = $(AM_CFLAGS) -DMODULE_REMOTE
|
919
shadowsocksr-libev/src/server/Makefile.in
Normal file
919
shadowsocksr-libev/src/server/Makefile.in
Normal file
@ -0,0 +1,919 @@
|
||||
# Makefile.in generated by automake 1.15 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2014 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = { \
|
||||
if test -z '$(MAKELEVEL)'; then \
|
||||
false; \
|
||||
elif test -n '$(MAKE_HOST)'; then \
|
||||
true; \
|
||||
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||
true; \
|
||||
else \
|
||||
false; \
|
||||
fi; \
|
||||
}
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
*) echo "am__make_running_with_option: internal error: invalid" \
|
||||
"target option '$${target_option-}' specified" >&2; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
has_opt=no; \
|
||||
sane_makeflags=$$MAKEFLAGS; \
|
||||
if $(am__is_gnu_make); then \
|
||||
sane_makeflags=$$MFLAGS; \
|
||||
else \
|
||||
case $$MAKEFLAGS in \
|
||||
*\\[\ \ ]*) \
|
||||
bs=\\; \
|
||||
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
|
||||
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
|
||||
esac; \
|
||||
fi; \
|
||||
skip_next=no; \
|
||||
strip_trailopt () \
|
||||
{ \
|
||||
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
|
||||
}; \
|
||||
for flg in $$sane_makeflags; do \
|
||||
test $$skip_next = yes && { skip_next=no; continue; }; \
|
||||
case $$flg in \
|
||||
*=*|--*) continue;; \
|
||||
-*I) strip_trailopt 'I'; skip_next=yes;; \
|
||||
-*I?*) strip_trailopt 'I';; \
|
||||
-*O) strip_trailopt 'O'; skip_next=yes;; \
|
||||
-*O?*) strip_trailopt 'O';; \
|
||||
-*l) strip_trailopt 'l'; skip_next=yes;; \
|
||||
-*l?*) strip_trailopt 'l';; \
|
||||
-[dEDm]) skip_next=yes;; \
|
||||
-[JT]) skip_next=yes;; \
|
||||
esac; \
|
||||
case $$flg in \
|
||||
*$$target_option*) has_opt=yes; break;; \
|
||||
esac; \
|
||||
done; \
|
||||
test $$has_opt = yes
|
||||
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
|
||||
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkglibexecdir = $(libexecdir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@am__append_1 = -I$(top_srcdir)/libev \
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@ -I$(top_srcdir)/libudns \
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@ -I$(top_srcdir)/libsodium/src/libsodium/include
|
||||
@USE_SYSTEM_SHARED_LIB_TRUE@am__append_2 = -lev -lsodium -lm
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@am__append_3 = $(top_builddir)/libev/libev.la \
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@ $(top_builddir)/libsodium/src/libsodium/libsodium.la
|
||||
|
||||
bin_PROGRAMS = ss-server$(EXEEXT) ss-check$(EXEEXT)
|
||||
@USE_SYSTEM_SHARED_LIB_TRUE@am__append_4 = -ludns
|
||||
@USE_SYSTEM_SHARED_LIB_FALSE@am__append_5 = $(top_builddir)/libudns/libudns.la
|
||||
subdir = server
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_pthread.m4 \
|
||||
$(top_srcdir)/m4/ax_tls.m4 $(top_srcdir)/m4/inet_ntop.m4 \
|
||||
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
|
||||
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
|
||||
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/mbedtls.m4 \
|
||||
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/pcre.m4 \
|
||||
$(top_srcdir)/m4/polarssl.m4 \
|
||||
$(top_srcdir)/m4/stack-protector.m4 $(top_srcdir)/m4/zlib.m4 \
|
||||
$(top_srcdir)/libev/libev.m4 $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||
PROGRAMS = $(bin_PROGRAMS)
|
||||
am_ss_check_OBJECTS = ss_check-check.$(OBJEXT)
|
||||
ss_check_OBJECTS = $(am_ss_check_OBJECTS)
|
||||
am__DEPENDENCIES_1 =
|
||||
am__DEPENDENCIES_2 = $(top_builddir)/libipset/libipset.la \
|
||||
$(top_builddir)/libcork/libcork.la $(am__DEPENDENCIES_1) \
|
||||
$(am__DEPENDENCIES_1) $(am__append_3)
|
||||
ss_check_DEPENDENCIES = $(am__DEPENDENCIES_2)
|
||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||
am__v_lt_0 = --silent
|
||||
am__v_lt_1 =
|
||||
ss_check_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_check_CFLAGS) \
|
||||
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
am__objects_1 = ss_server-http.$(OBJEXT) ss_server-tls.$(OBJEXT) \
|
||||
ss_server-rule.$(OBJEXT)
|
||||
am_ss_server_OBJECTS = ss_server-utils.$(OBJEXT) \
|
||||
ss_server-netutils.$(OBJEXT) ss_server-jconf.$(OBJEXT) \
|
||||
ss_server-json.$(OBJEXT) ss_server-encrypt.$(OBJEXT) \
|
||||
ss_server-udprelay.$(OBJEXT) ss_server-cache.$(OBJEXT) \
|
||||
ss_server-acl.$(OBJEXT) ss_server-resolv.$(OBJEXT) \
|
||||
ss_server-server.$(OBJEXT) $(am__objects_1)
|
||||
ss_server_OBJECTS = $(am_ss_server_OBJECTS)
|
||||
ss_server_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
|
||||
$(am__append_5)
|
||||
ss_server_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ss_server_CFLAGS) \
|
||||
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
am__v_P_1 = :
|
||||
AM_V_GEN = $(am__v_GEN_@AM_V@)
|
||||
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
|
||||
am__v_GEN_0 = @echo " GEN " $@;
|
||||
am__v_GEN_1 =
|
||||
AM_V_at = $(am__v_at_@AM_V@)
|
||||
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
|
||||
am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
|
||||
depcomp = $(SHELL) $(top_srcdir)/auto/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__mv = mv -f
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
|
||||
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
|
||||
$(AM_CFLAGS) $(CFLAGS)
|
||||
AM_V_CC = $(am__v_CC_@AM_V@)
|
||||
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
|
||||
am__v_CC_0 = @echo " CC " $@;
|
||||
am__v_CC_1 =
|
||||
CCLD = $(CC)
|
||||
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
|
||||
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
|
||||
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||
am__v_CCLD_1 =
|
||||
SOURCES = $(ss_check_SOURCES) $(ss_server_SOURCES)
|
||||
DIST_SOURCES = $(ss_check_SOURCES) $(ss_server_SOURCES)
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
*) (install-info --version) >/dev/null 2>&1;; \
|
||||
esac
|
||||
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
|
||||
# Read a list of newline-separated strings from the standard input,
|
||||
# and print each of them once, without duplicates. Input order is
|
||||
# *not* preserved.
|
||||
am__uniquify_input = $(AWK) '\
|
||||
BEGIN { nonempty = 0; } \
|
||||
{ items[$$0] = 1; nonempty = 1; } \
|
||||
END { if (nonempty) { for (i in items) print i; }; } \
|
||||
'
|
||||
# Make sure the list of sources is unique. This is necessary because,
|
||||
# e.g., the same source file might be shared among _SOURCES variables
|
||||
# for different programs/libraries.
|
||||
am__define_uniq_tagged_files = \
|
||||
list='$(am__tagged_files)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/auto/depcomp
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AR = @AR@
|
||||
ASCIIDOC = @ASCIIDOC@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GREP = @GREP@
|
||||
GZIP = @GZIP@
|
||||
INET_NTOP_LIB = @INET_NTOP_LIB@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LD = @LD@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBPCRE = @LIBPCRE@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAINT = @MAINT@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
MV = @MV@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_URL = @PACKAGE_URL@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PCRE_CONFIG = @PCRE_CONFIG@
|
||||
PTHREAD_CC = @PTHREAD_CC@
|
||||
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
|
||||
PTHREAD_LIBS = @PTHREAD_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
XMLTO = @XMLTO@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
ax_pthread_config = @ax_pthread_config@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pcre_pcreh = @pcre_pcreh@
|
||||
pcreh = @pcreh@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
runstatedir = @runstatedir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
subdirs = @subdirs@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VERSION_INFO = 2:0:0
|
||||
AM_CFLAGS = -g -O2 -Wall -Werror -Wno-deprecated-declarations \
|
||||
-fno-strict-aliasing -std=gnu99 -D_GNU_SOURCE \
|
||||
$(PTHREAD_CFLAGS) $(am__append_1) \
|
||||
-I$(top_srcdir)/libipset/include \
|
||||
-I$(top_srcdir)/libcork/include $(LIBPCRE_CFLAGS)
|
||||
SS_COMMON_LIBS = $(top_builddir)/libipset/libipset.la \
|
||||
$(top_builddir)/libcork/libcork.la $(INET_NTOP_LIB) \
|
||||
$(LIBPCRE_LIBS) $(am__append_2) $(am__append_3)
|
||||
sni_src = http.c \
|
||||
tls.c \
|
||||
rule.c
|
||||
|
||||
ss_check_SOURCES = check.c
|
||||
ss_server_SOURCES = utils.c \
|
||||
netutils.c \
|
||||
jconf.c \
|
||||
json.c \
|
||||
encrypt.c \
|
||||
udprelay.c \
|
||||
cache.c \
|
||||
acl.c \
|
||||
resolv.c \
|
||||
server.c \
|
||||
$(sni_src)
|
||||
|
||||
ss_check_LDADD = $(SS_COMMON_LIBS)
|
||||
ss_server_LDADD = $(SS_COMMON_LIBS) $(am__append_4) $(am__append_5)
|
||||
ss_check_CFLAGS = $(AM_CFLAGS)
|
||||
ss_server_CFLAGS = $(AM_CFLAGS) -DMODULE_REMOTE
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o .obj
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
|
||||
&& { if test -f $@; then exit 0; else break; fi; }; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign server/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign server/Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||
@$(NORMAL_INSTALL)
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
if test -n "$$list"; then \
|
||||
echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
|
||||
$(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
|
||||
fi; \
|
||||
for p in $$list; do echo "$$p $$p"; done | \
|
||||
sed 's/$(EXEEXT)$$//' | \
|
||||
while read p p1; do if test -f $$p \
|
||||
|| test -f $$p1 \
|
||||
; then echo "$$p"; echo "$$p"; else :; fi; \
|
||||
done | \
|
||||
sed -e 'p;s,.*/,,;n;h' \
|
||||
-e 's|.*|.|' \
|
||||
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
|
||||
sed 'N;N;N;s,\n, ,g' | \
|
||||
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
|
||||
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
|
||||
if ($$2 == $$4) files[d] = files[d] " " $$1; \
|
||||
else { print "f", $$3 "/" $$4, $$1; } } \
|
||||
END { for (d in files) print "f", d, files[d] }' | \
|
||||
while read type dir files; do \
|
||||
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
|
||||
test -z "$$files" || { \
|
||||
echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
|
||||
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
|
||||
} \
|
||||
; done
|
||||
|
||||
uninstall-binPROGRAMS:
|
||||
@$(NORMAL_UNINSTALL)
|
||||
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
|
||||
files=`for p in $$list; do echo "$$p"; done | \
|
||||
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
|
||||
-e 's/$$/$(EXEEXT)/' \
|
||||
`; \
|
||||
test -n "$$list" || exit 0; \
|
||||
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
|
||||
cd "$(DESTDIR)$(bindir)" && rm -f $$files
|
||||
|
||||
clean-binPROGRAMS:
|
||||
@list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
|
||||
echo " rm -f" $$list; \
|
||||
rm -f $$list || exit $$?; \
|
||||
test -n "$(EXEEXT)" || exit 0; \
|
||||
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
|
||||
echo " rm -f" $$list; \
|
||||
rm -f $$list
|
||||
|
||||
ss-check$(EXEEXT): $(ss_check_OBJECTS) $(ss_check_DEPENDENCIES) $(EXTRA_ss_check_DEPENDENCIES)
|
||||
@rm -f ss-check$(EXEEXT)
|
||||
$(AM_V_CCLD)$(ss_check_LINK) $(ss_check_OBJECTS) $(ss_check_LDADD) $(LIBS)
|
||||
|
||||
ss-server$(EXEEXT): $(ss_server_OBJECTS) $(ss_server_DEPENDENCIES) $(EXTRA_ss_server_DEPENDENCIES)
|
||||
@rm -f ss-server$(EXEEXT)
|
||||
$(AM_V_CCLD)$(ss_server_LINK) $(ss_server_OBJECTS) $(ss_server_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_check-check.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-acl.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-cache.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-encrypt.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-http.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-jconf.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-json.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-netutils.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-resolv.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ss_server-rule.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-tls.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@
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
|
||||
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
|
||||
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
.c.lo:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
|
||||
@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
|
||||
@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
ss_check-check.o: check.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_check_CFLAGS) $(CFLAGS) -MT ss_check-check.o -MD -MP -MF $(DEPDIR)/ss_check-check.Tpo -c -o ss_check-check.o `test -f 'check.c' || echo '$(srcdir)/'`check.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_check-check.Tpo $(DEPDIR)/ss_check-check.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='check.c' object='ss_check-check.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_check_CFLAGS) $(CFLAGS) -c -o ss_check-check.o `test -f 'check.c' || echo '$(srcdir)/'`check.c
|
||||
|
||||
ss_check-check.obj: check.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_check_CFLAGS) $(CFLAGS) -MT ss_check-check.obj -MD -MP -MF $(DEPDIR)/ss_check-check.Tpo -c -o ss_check-check.obj `if test -f 'check.c'; then $(CYGPATH_W) 'check.c'; else $(CYGPATH_W) '$(srcdir)/check.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_check-check.Tpo $(DEPDIR)/ss_check-check.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='check.c' object='ss_check-check.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_check_CFLAGS) $(CFLAGS) -c -o ss_check-check.obj `if test -f 'check.c'; then $(CYGPATH_W) 'check.c'; else $(CYGPATH_W) '$(srcdir)/check.c'; fi`
|
||||
|
||||
ss_server-utils.o: utils.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-utils.o -MD -MP -MF $(DEPDIR)/ss_server-utils.Tpo -c -o ss_server-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-utils.Tpo $(DEPDIR)/ss_server-utils.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils.c' object='ss_server-utils.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
|
||||
|
||||
ss_server-utils.obj: utils.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-utils.obj -MD -MP -MF $(DEPDIR)/ss_server-utils.Tpo -c -o ss_server-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-utils.Tpo $(DEPDIR)/ss_server-utils.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='utils.c' object='ss_server-utils.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
|
||||
|
||||
ss_server-netutils.o: netutils.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-netutils.o -MD -MP -MF $(DEPDIR)/ss_server-netutils.Tpo -c -o ss_server-netutils.o `test -f 'netutils.c' || echo '$(srcdir)/'`netutils.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-netutils.Tpo $(DEPDIR)/ss_server-netutils.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netutils.c' object='ss_server-netutils.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-netutils.o `test -f 'netutils.c' || echo '$(srcdir)/'`netutils.c
|
||||
|
||||
ss_server-netutils.obj: netutils.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-netutils.obj -MD -MP -MF $(DEPDIR)/ss_server-netutils.Tpo -c -o ss_server-netutils.obj `if test -f 'netutils.c'; then $(CYGPATH_W) 'netutils.c'; else $(CYGPATH_W) '$(srcdir)/netutils.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-netutils.Tpo $(DEPDIR)/ss_server-netutils.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netutils.c' object='ss_server-netutils.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-netutils.obj `if test -f 'netutils.c'; then $(CYGPATH_W) 'netutils.c'; else $(CYGPATH_W) '$(srcdir)/netutils.c'; fi`
|
||||
|
||||
ss_server-jconf.o: jconf.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-jconf.o -MD -MP -MF $(DEPDIR)/ss_server-jconf.Tpo -c -o ss_server-jconf.o `test -f 'jconf.c' || echo '$(srcdir)/'`jconf.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-jconf.Tpo $(DEPDIR)/ss_server-jconf.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='jconf.c' object='ss_server-jconf.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-jconf.o `test -f 'jconf.c' || echo '$(srcdir)/'`jconf.c
|
||||
|
||||
ss_server-jconf.obj: jconf.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-jconf.obj -MD -MP -MF $(DEPDIR)/ss_server-jconf.Tpo -c -o ss_server-jconf.obj `if test -f 'jconf.c'; then $(CYGPATH_W) 'jconf.c'; else $(CYGPATH_W) '$(srcdir)/jconf.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-jconf.Tpo $(DEPDIR)/ss_server-jconf.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='jconf.c' object='ss_server-jconf.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-jconf.obj `if test -f 'jconf.c'; then $(CYGPATH_W) 'jconf.c'; else $(CYGPATH_W) '$(srcdir)/jconf.c'; fi`
|
||||
|
||||
ss_server-json.o: json.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-json.o -MD -MP -MF $(DEPDIR)/ss_server-json.Tpo -c -o ss_server-json.o `test -f 'json.c' || echo '$(srcdir)/'`json.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-json.Tpo $(DEPDIR)/ss_server-json.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='json.c' object='ss_server-json.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-json.o `test -f 'json.c' || echo '$(srcdir)/'`json.c
|
||||
|
||||
ss_server-json.obj: json.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-json.obj -MD -MP -MF $(DEPDIR)/ss_server-json.Tpo -c -o ss_server-json.obj `if test -f 'json.c'; then $(CYGPATH_W) 'json.c'; else $(CYGPATH_W) '$(srcdir)/json.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-json.Tpo $(DEPDIR)/ss_server-json.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='json.c' object='ss_server-json.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-json.obj `if test -f 'json.c'; then $(CYGPATH_W) 'json.c'; else $(CYGPATH_W) '$(srcdir)/json.c'; fi`
|
||||
|
||||
ss_server-encrypt.o: encrypt.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-encrypt.o -MD -MP -MF $(DEPDIR)/ss_server-encrypt.Tpo -c -o ss_server-encrypt.o `test -f 'encrypt.c' || echo '$(srcdir)/'`encrypt.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-encrypt.Tpo $(DEPDIR)/ss_server-encrypt.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='encrypt.c' object='ss_server-encrypt.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-encrypt.o `test -f 'encrypt.c' || echo '$(srcdir)/'`encrypt.c
|
||||
|
||||
ss_server-encrypt.obj: encrypt.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-encrypt.obj -MD -MP -MF $(DEPDIR)/ss_server-encrypt.Tpo -c -o ss_server-encrypt.obj `if test -f 'encrypt.c'; then $(CYGPATH_W) 'encrypt.c'; else $(CYGPATH_W) '$(srcdir)/encrypt.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-encrypt.Tpo $(DEPDIR)/ss_server-encrypt.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='encrypt.c' object='ss_server-encrypt.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-encrypt.obj `if test -f 'encrypt.c'; then $(CYGPATH_W) 'encrypt.c'; else $(CYGPATH_W) '$(srcdir)/encrypt.c'; fi`
|
||||
|
||||
ss_server-udprelay.o: udprelay.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-udprelay.o -MD -MP -MF $(DEPDIR)/ss_server-udprelay.Tpo -c -o ss_server-udprelay.o `test -f 'udprelay.c' || echo '$(srcdir)/'`udprelay.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-udprelay.Tpo $(DEPDIR)/ss_server-udprelay.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='udprelay.c' object='ss_server-udprelay.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-udprelay.o `test -f 'udprelay.c' || echo '$(srcdir)/'`udprelay.c
|
||||
|
||||
ss_server-udprelay.obj: udprelay.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-udprelay.obj -MD -MP -MF $(DEPDIR)/ss_server-udprelay.Tpo -c -o ss_server-udprelay.obj `if test -f 'udprelay.c'; then $(CYGPATH_W) 'udprelay.c'; else $(CYGPATH_W) '$(srcdir)/udprelay.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-udprelay.Tpo $(DEPDIR)/ss_server-udprelay.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='udprelay.c' object='ss_server-udprelay.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-udprelay.obj `if test -f 'udprelay.c'; then $(CYGPATH_W) 'udprelay.c'; else $(CYGPATH_W) '$(srcdir)/udprelay.c'; fi`
|
||||
|
||||
ss_server-cache.o: cache.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-cache.o -MD -MP -MF $(DEPDIR)/ss_server-cache.Tpo -c -o ss_server-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-cache.Tpo $(DEPDIR)/ss_server-cache.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cache.c' object='ss_server-cache.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-cache.o `test -f 'cache.c' || echo '$(srcdir)/'`cache.c
|
||||
|
||||
ss_server-cache.obj: cache.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-cache.obj -MD -MP -MF $(DEPDIR)/ss_server-cache.Tpo -c -o ss_server-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-cache.Tpo $(DEPDIR)/ss_server-cache.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cache.c' object='ss_server-cache.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-cache.obj `if test -f 'cache.c'; then $(CYGPATH_W) 'cache.c'; else $(CYGPATH_W) '$(srcdir)/cache.c'; fi`
|
||||
|
||||
ss_server-acl.o: acl.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-acl.o -MD -MP -MF $(DEPDIR)/ss_server-acl.Tpo -c -o ss_server-acl.o `test -f 'acl.c' || echo '$(srcdir)/'`acl.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-acl.Tpo $(DEPDIR)/ss_server-acl.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='acl.c' object='ss_server-acl.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-acl.o `test -f 'acl.c' || echo '$(srcdir)/'`acl.c
|
||||
|
||||
ss_server-acl.obj: acl.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-acl.obj -MD -MP -MF $(DEPDIR)/ss_server-acl.Tpo -c -o ss_server-acl.obj `if test -f 'acl.c'; then $(CYGPATH_W) 'acl.c'; else $(CYGPATH_W) '$(srcdir)/acl.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-acl.Tpo $(DEPDIR)/ss_server-acl.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='acl.c' object='ss_server-acl.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-acl.obj `if test -f 'acl.c'; then $(CYGPATH_W) 'acl.c'; else $(CYGPATH_W) '$(srcdir)/acl.c'; fi`
|
||||
|
||||
ss_server-resolv.o: resolv.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-resolv.o -MD -MP -MF $(DEPDIR)/ss_server-resolv.Tpo -c -o ss_server-resolv.o `test -f 'resolv.c' || echo '$(srcdir)/'`resolv.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-resolv.Tpo $(DEPDIR)/ss_server-resolv.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='resolv.c' object='ss_server-resolv.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-resolv.o `test -f 'resolv.c' || echo '$(srcdir)/'`resolv.c
|
||||
|
||||
ss_server-resolv.obj: resolv.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-resolv.obj -MD -MP -MF $(DEPDIR)/ss_server-resolv.Tpo -c -o ss_server-resolv.obj `if test -f 'resolv.c'; then $(CYGPATH_W) 'resolv.c'; else $(CYGPATH_W) '$(srcdir)/resolv.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-resolv.Tpo $(DEPDIR)/ss_server-resolv.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='resolv.c' object='ss_server-resolv.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-resolv.obj `if test -f 'resolv.c'; then $(CYGPATH_W) 'resolv.c'; else $(CYGPATH_W) '$(srcdir)/resolv.c'; fi`
|
||||
|
||||
ss_server-server.o: server.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-server.o -MD -MP -MF $(DEPDIR)/ss_server-server.Tpo -c -o ss_server-server.o `test -f 'server.c' || echo '$(srcdir)/'`server.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-server.Tpo $(DEPDIR)/ss_server-server.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server.c' object='ss_server-server.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-server.o `test -f 'server.c' || echo '$(srcdir)/'`server.c
|
||||
|
||||
ss_server-server.obj: server.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-server.obj -MD -MP -MF $(DEPDIR)/ss_server-server.Tpo -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_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-server.Tpo $(DEPDIR)/ss_server-server.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server.c' object='ss_server-server.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(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_server-http.o: http.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-http.o -MD -MP -MF $(DEPDIR)/ss_server-http.Tpo -c -o ss_server-http.o `test -f 'http.c' || echo '$(srcdir)/'`http.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-http.Tpo $(DEPDIR)/ss_server-http.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http.c' object='ss_server-http.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-http.o `test -f 'http.c' || echo '$(srcdir)/'`http.c
|
||||
|
||||
ss_server-http.obj: http.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-http.obj -MD -MP -MF $(DEPDIR)/ss_server-http.Tpo -c -o ss_server-http.obj `if test -f 'http.c'; then $(CYGPATH_W) 'http.c'; else $(CYGPATH_W) '$(srcdir)/http.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-http.Tpo $(DEPDIR)/ss_server-http.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http.c' object='ss_server-http.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-http.obj `if test -f 'http.c'; then $(CYGPATH_W) 'http.c'; else $(CYGPATH_W) '$(srcdir)/http.c'; fi`
|
||||
|
||||
ss_server-tls.o: tls.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-tls.o -MD -MP -MF $(DEPDIR)/ss_server-tls.Tpo -c -o ss_server-tls.o `test -f 'tls.c' || echo '$(srcdir)/'`tls.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-tls.Tpo $(DEPDIR)/ss_server-tls.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tls.c' object='ss_server-tls.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-tls.o `test -f 'tls.c' || echo '$(srcdir)/'`tls.c
|
||||
|
||||
ss_server-tls.obj: tls.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-tls.obj -MD -MP -MF $(DEPDIR)/ss_server-tls.Tpo -c -o ss_server-tls.obj `if test -f 'tls.c'; then $(CYGPATH_W) 'tls.c'; else $(CYGPATH_W) '$(srcdir)/tls.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-tls.Tpo $(DEPDIR)/ss_server-tls.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tls.c' object='ss_server-tls.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-tls.obj `if test -f 'tls.c'; then $(CYGPATH_W) 'tls.c'; else $(CYGPATH_W) '$(srcdir)/tls.c'; fi`
|
||||
|
||||
ss_server-rule.o: rule.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-rule.o -MD -MP -MF $(DEPDIR)/ss_server-rule.Tpo -c -o ss_server-rule.o `test -f 'rule.c' || echo '$(srcdir)/'`rule.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-rule.Tpo $(DEPDIR)/ss_server-rule.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rule.c' object='ss_server-rule.o' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-rule.o `test -f 'rule.c' || echo '$(srcdir)/'`rule.c
|
||||
|
||||
ss_server-rule.obj: rule.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -MT ss_server-rule.obj -MD -MP -MF $(DEPDIR)/ss_server-rule.Tpo -c -o ss_server-rule.obj `if test -f 'rule.c'; then $(CYGPATH_W) 'rule.c'; else $(CYGPATH_W) '$(srcdir)/rule.c'; fi`
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ss_server-rule.Tpo $(DEPDIR)/ss_server-rule.Po
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rule.c' object='ss_server-rule.obj' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ss_server_CFLAGS) $(CFLAGS) -c -o ss_server-rule.obj `if test -f 'rule.c'; then $(CYGPATH_W) 'rule.c'; else $(CYGPATH_W) '$(srcdir)/rule.c'; fi`
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
clean-libtool:
|
||||
-rm -rf .libs _libs
|
||||
|
||||
ID: $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); mkid -fID $$unique
|
||||
tags: tags-am
|
||||
TAGS: tags
|
||||
|
||||
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
set x; \
|
||||
here=`pwd`; \
|
||||
$(am__define_uniq_tagged_files); \
|
||||
shift; \
|
||||
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
if test $$# -gt 0; then \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
"$$@" $$unique; \
|
||||
else \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$unique; \
|
||||
fi; \
|
||||
fi
|
||||
ctags: ctags-am
|
||||
|
||||
CTAGS: ctags
|
||||
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
|
||||
$(am__define_uniq_tagged_files); \
|
||||
test -z "$(CTAGS_ARGS)$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& $(am__cd) $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) "$$here"
|
||||
cscopelist: cscopelist-am
|
||||
|
||||
cscopelist-am: $(am__tagged_files)
|
||||
list='$(am__tagged_files)'; \
|
||||
case "$(srcdir)" in \
|
||||
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
|
||||
*) sdir=$(subdir)/$(srcdir) ;; \
|
||||
esac; \
|
||||
for i in $$list; do \
|
||||
if test -f "$$i"; then \
|
||||
echo "$(subdir)/$$i"; \
|
||||
else \
|
||||
echo "$$sdir/$$i"; \
|
||||
fi; \
|
||||
done >> $(top_builddir)/cscope.files
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d "$(distdir)/$$file"; then \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
|
||||
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
|
||||
fi; \
|
||||
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
|
||||
else \
|
||||
test -f "$(distdir)/$$file" \
|
||||
|| cp -p $$d/$$file "$(distdir)/$$file" \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(PROGRAMS)
|
||||
installdirs:
|
||||
for dir in "$(DESTDIR)$(bindir)"; do \
|
||||
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||
done
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
if test -z '$(STRIP)'; then \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
install; \
|
||||
else \
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
|
||||
fi
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
html-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-dvi-am:
|
||||
|
||||
install-exec-am: install-binPROGRAMS
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-html-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-info-am:
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-pdf-am:
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
install-ps-am:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-binPROGRAMS
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
|
||||
clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \
|
||||
ctags ctags-am distclean distclean-compile distclean-generic \
|
||||
distclean-libtool distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-binPROGRAMS \
|
||||
install-data install-data-am install-dvi install-dvi-am \
|
||||
install-exec install-exec-am install-html install-html-am \
|
||||
install-info install-info-am install-man install-pdf \
|
||||
install-pdf-am install-ps install-ps-am install-strip \
|
||||
installcheck installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||
tags tags-am uninstall uninstall-am uninstall-binPROGRAMS
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
3
shadowsocksr-libev/src/server/README.md
Normal file
3
shadowsocksr-libev/src/server/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# server
|
||||
|
||||
`ss-server` and `ss-check` from https://github.com/ywb94/shadowsocks-libev
|
597
shadowsocksr-libev/src/server/acl.c
Normal file
597
shadowsocksr-libev/src/server/acl.c
Normal file
@ -0,0 +1,597 @@
|
||||
/*
|
||||
* acl.c - Manage the ACL (Access Control List)
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* This file is part of the shadowsocks-libev.
|
||||
*
|
||||
* shadowsocks-libev is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* shadowsocks-libev is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with shadowsocks-libev; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ipset/ipset.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "rule.h"
|
||||
#include "utils.h"
|
||||
#include "cache.h"
|
||||
#include "acl.h"
|
||||
|
||||
static struct ip_set white_list_ipv4;
|
||||
static struct ip_set white_list_ipv6;
|
||||
|
||||
static struct ip_set black_list_ipv4;
|
||||
static struct ip_set black_list_ipv6;
|
||||
|
||||
static struct cork_dllist black_list_rules;
|
||||
static struct cork_dllist white_list_rules;
|
||||
|
||||
static int acl_mode = BLACK_LIST;
|
||||
|
||||
static struct cache *block_list;
|
||||
|
||||
static struct ip_set outbound_block_list_ipv4;
|
||||
static struct ip_set outbound_block_list_ipv6;
|
||||
static struct cork_dllist outbound_block_list_rules;
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define NO_FIREWALL_MODE 0
|
||||
#define IPTABLES_MODE 1
|
||||
#define FIREWALLD_MODE 2
|
||||
|
||||
static FILE *shell_stdin;
|
||||
static int mode = NO_FIREWALL_MODE;
|
||||
|
||||
static char chain_name[64];
|
||||
static char *iptables_init_chain =
|
||||
"iptables -N %s; iptables -F %s; iptables -A OUTPUT -p tcp --tcp-flags RST RST -j %s";
|
||||
static char *iptables_remove_chain =
|
||||
"iptables -D OUTPUT -p tcp --tcp-flags RST RST -j %s; iptables -F %s; iptables -X %s";
|
||||
static char *iptables_add_rule = "iptables -A %s -d %s -j DROP";
|
||||
static char *iptables_remove_rule = "iptables -D %s -d %s -j DROP";
|
||||
|
||||
static char *ip6tables_init_chain =
|
||||
"ip6tables -N %s; ip6tables -F %s; ip6tables -A OUTPUT -p tcp --tcp-flags RST RST -j %s";
|
||||
static char *ip6tables_remove_chain =
|
||||
"ip6tables -D OUTPUT -p tcp --tcp-flags RST RST -j %s; ip6tables -F %s; ip6tables -X %s";
|
||||
static char *ip6tables_add_rule = "ip6tables -A %s -d %s -j DROP";
|
||||
static char *ip6tables_remove_rule = "ip6tables -D %s -d %s -j DROP";
|
||||
|
||||
static char *firewalld_init_chain =
|
||||
"firewall-cmd --direct --add-chain ipv4 filter %s; \
|
||||
firewall-cmd --direct --passthrough ipv4 -F %s; \
|
||||
firewall-cmd --direct --passthrough ipv4 -A OUTPUT -p tcp --tcp-flags RST RST -j %s";
|
||||
static char *firewalld_remove_chain =
|
||||
"firewall-cmd --direct --passthrough ipv4 -D OUTPUT -p tcp --tcp-flags RST RST -j %s; \
|
||||
firewall-cmd --direct --passthrough ipv4 -F %s; \
|
||||
firewall-cmd --direct --remove-chain ipv4 filter %s";
|
||||
static char *firewalld_add_rule = "firewall-cmd --direct --passthrough ipv4 -A %s -d %s -j DROP";
|
||||
static char *firewalld_remove_rule = "firewall-cmd --direct --passthrough ipv4 -D %s -d %s -j DROP";
|
||||
|
||||
static char *firewalld6_init_chain =
|
||||
"firewall-cmd --direct --add-chain ipv6 filter %s; \
|
||||
firewall-cmd --direct --passthrough ipv6 -F %s; \
|
||||
firewall-cmd --direct --passthrough ipv6 -A OUTPUT -p tcp --tcp-flags RST RST -j %s";
|
||||
static char *firewalld6_remove_chain =
|
||||
"firewall-cmd --direct --passthrough ipv6 -D OUTPUT -p tcp --tcp-flags RST RST -j %s; \
|
||||
firewall-cmd --direct --passthrough ipv6 -F %s; \
|
||||
firewall-cmd --direct --remove-chain ipv6 filter %s";
|
||||
static char *firewalld6_add_rule = "firewall-cmd --direct --passthrough ipv6 -A %s -d %s -j DROP";
|
||||
static char *firewalld6_remove_rule = "firewall-cmd --direct --passthrough ipv6 -D %s -d %s -j DROP";
|
||||
|
||||
static int
|
||||
run_cmd(const char *cmd)
|
||||
{
|
||||
int ret = 0;
|
||||
char cmdstring[256];
|
||||
|
||||
sprintf(cmdstring, "%s\n", cmd);
|
||||
size_t len = strlen(cmdstring);
|
||||
|
||||
if (shell_stdin != NULL) {
|
||||
ret = fwrite(cmdstring, 1, len, shell_stdin);
|
||||
fflush(shell_stdin);
|
||||
}
|
||||
|
||||
return ret == len;
|
||||
}
|
||||
|
||||
static int
|
||||
init_firewall()
|
||||
{
|
||||
int ret = 0;
|
||||
char cli[256];
|
||||
FILE *fp;
|
||||
|
||||
if (getuid() != 0)
|
||||
return -1;
|
||||
|
||||
sprintf(cli, "firewall-cmd --version 2>&1");
|
||||
fp = popen(cli, "r");
|
||||
|
||||
if (fp == NULL)
|
||||
return -1;
|
||||
|
||||
if (pclose(fp) == 0) {
|
||||
mode = FIREWALLD_MODE;
|
||||
} else {
|
||||
/* Check whether we have permission to operate iptables.
|
||||
* Note that checking `iptables --version` is insufficient:
|
||||
* eg, running within a child user namespace.
|
||||
*/
|
||||
sprintf(cli, "iptables -L 2>&1");
|
||||
fp = popen(cli, "r");
|
||||
if (fp == NULL)
|
||||
return -1;
|
||||
if (pclose(fp) == 0)
|
||||
mode = IPTABLES_MODE;
|
||||
}
|
||||
|
||||
sprintf(chain_name, "SHADOWSOCKS_LIBEV_%d", getpid());
|
||||
|
||||
if (mode == FIREWALLD_MODE) {
|
||||
sprintf(cli, firewalld6_init_chain, chain_name, chain_name, chain_name);
|
||||
ret |= system(cli);
|
||||
sprintf(cli, firewalld_init_chain, chain_name, chain_name, chain_name);
|
||||
ret |= system(cli);
|
||||
} else if (mode == IPTABLES_MODE) {
|
||||
sprintf(cli, ip6tables_init_chain, chain_name, chain_name, chain_name);
|
||||
ret |= system(cli);
|
||||
sprintf(cli, iptables_init_chain, chain_name, chain_name, chain_name);
|
||||
ret |= system(cli);
|
||||
}
|
||||
|
||||
shell_stdin = popen("/bin/sh", "w");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
reset_firewall()
|
||||
{
|
||||
int ret = 0;
|
||||
char cli[256];
|
||||
|
||||
if (getuid() != 0)
|
||||
return -1;
|
||||
|
||||
if (mode == IPTABLES_MODE) {
|
||||
sprintf(cli, ip6tables_remove_chain, chain_name, chain_name, chain_name);
|
||||
ret |= system(cli);
|
||||
sprintf(cli, iptables_remove_chain, chain_name, chain_name, chain_name);
|
||||
ret |= system(cli);
|
||||
} else if (mode == FIREWALLD_MODE) {
|
||||
sprintf(cli, firewalld6_remove_chain, chain_name, chain_name, chain_name);
|
||||
ret |= system(cli);
|
||||
sprintf(cli, firewalld_remove_chain, chain_name, chain_name, chain_name);
|
||||
ret |= system(cli);
|
||||
}
|
||||
|
||||
if (shell_stdin != NULL) {
|
||||
run_cmd("exit 0");
|
||||
pclose(shell_stdin);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
set_firewall_rule(char *addr, int add)
|
||||
{
|
||||
char cli[256];
|
||||
struct cork_ip ip;
|
||||
|
||||
if (getuid() != 0)
|
||||
return -1;
|
||||
|
||||
if (cork_ip_init(&ip, addr))
|
||||
return -1;
|
||||
|
||||
if (add) {
|
||||
if (mode == IPTABLES_MODE)
|
||||
sprintf(cli, ip.version == 4 ? iptables_add_rule : ip6tables_add_rule,
|
||||
chain_name, addr);
|
||||
else if (mode == FIREWALLD_MODE)
|
||||
sprintf(cli, ip.version == 4 ? firewalld_add_rule : firewalld6_add_rule,
|
||||
chain_name, addr);
|
||||
return run_cmd(cli);
|
||||
} else {
|
||||
if (mode == IPTABLES_MODE)
|
||||
sprintf(cli, ip.version == 4 ? iptables_remove_rule : ip6tables_remove_rule,
|
||||
chain_name, addr);
|
||||
else if (mode == FIREWALLD_MODE)
|
||||
sprintf(cli, ip.version == 4 ? firewalld_remove_rule : firewalld6_remove_rule,
|
||||
chain_name, addr);
|
||||
return run_cmd(cli);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
free_firewall_rule(void *key, void *element)
|
||||
{
|
||||
if (key == NULL)
|
||||
return;
|
||||
char *addr = (char *)key;
|
||||
set_firewall_rule(addr, 0);
|
||||
ss_free(element);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
init_block_list(int firewall)
|
||||
{
|
||||
// Initialize cache
|
||||
#ifdef __linux__
|
||||
if (firewall)
|
||||
init_firewall();
|
||||
else
|
||||
mode = NO_FIREWALL_MODE;
|
||||
cache_create(&block_list, 256, free_firewall_rule);
|
||||
#else
|
||||
cache_create(&block_list, 256, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
free_block_list()
|
||||
{
|
||||
#ifdef __linux__
|
||||
if (mode != NO_FIREWALL_MODE)
|
||||
reset_firewall();
|
||||
#endif
|
||||
cache_clear(block_list, 0); // Remove all items
|
||||
}
|
||||
|
||||
int
|
||||
remove_from_block_list(char *addr)
|
||||
{
|
||||
size_t addr_len = strlen(addr);
|
||||
return cache_remove(block_list, addr, addr_len);
|
||||
}
|
||||
|
||||
void
|
||||
clear_block_list()
|
||||
{
|
||||
cache_clear(block_list, 3600); // Clear items older than 1 hour
|
||||
}
|
||||
|
||||
int
|
||||
check_block_list(char *addr)
|
||||
{
|
||||
size_t addr_len = strlen(addr);
|
||||
|
||||
if (cache_key_exist(block_list, addr, addr_len)) {
|
||||
int *count = NULL;
|
||||
cache_lookup(block_list, addr, addr_len, &count);
|
||||
|
||||
if (count != NULL && *count > MAX_TRIES)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
update_block_list(char *addr, int err_level)
|
||||
{
|
||||
size_t addr_len = strlen(addr);
|
||||
|
||||
if (cache_key_exist(block_list, addr, addr_len)) {
|
||||
int *count = NULL;
|
||||
cache_lookup(block_list, addr, addr_len, &count);
|
||||
if (count != NULL) {
|
||||
if (*count > MAX_TRIES)
|
||||
return 1;
|
||||
(*count) += err_level;
|
||||
}
|
||||
} else if (err_level > 0) {
|
||||
int *count = (int *)ss_malloc(sizeof(int));
|
||||
*count = 1;
|
||||
cache_insert(block_list, addr, addr_len, count);
|
||||
#ifdef __linux__
|
||||
if (mode != NO_FIREWALL_MODE)
|
||||
set_firewall_rule(addr, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_addr_cidr(const char *str, char *host, int *cidr)
|
||||
{
|
||||
int ret = -1, n = 0;
|
||||
char *pch;
|
||||
|
||||
pch = strchr(str, '/');
|
||||
while (pch != NULL) {
|
||||
n++;
|
||||
ret = pch - str;
|
||||
pch = strchr(pch + 1, '/');
|
||||
}
|
||||
if (ret == -1) {
|
||||
strcpy(host, str);
|
||||
*cidr = -1;
|
||||
} else {
|
||||
memcpy(host, str, ret);
|
||||
host[ret] = '\0';
|
||||
*cidr = atoi(str + ret + 1);
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
trimwhitespace(char *str)
|
||||
{
|
||||
char *end;
|
||||
|
||||
// Trim leading space
|
||||
while (isspace(*str))
|
||||
str++;
|
||||
|
||||
if (*str == 0) // All spaces?
|
||||
return str;
|
||||
|
||||
// Trim trailing space
|
||||
end = str + strlen(str) - 1;
|
||||
while (end > str && isspace(*end))
|
||||
end--;
|
||||
|
||||
// Write new null terminator
|
||||
*(end + 1) = 0;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
int
|
||||
init_acl(const char *path)
|
||||
{
|
||||
// initialize ipset
|
||||
ipset_init_library();
|
||||
|
||||
ipset_init(&white_list_ipv4);
|
||||
ipset_init(&white_list_ipv6);
|
||||
ipset_init(&black_list_ipv4);
|
||||
ipset_init(&black_list_ipv6);
|
||||
ipset_init(&outbound_block_list_ipv4);
|
||||
ipset_init(&outbound_block_list_ipv6);
|
||||
|
||||
cork_dllist_init(&black_list_rules);
|
||||
cork_dllist_init(&white_list_rules);
|
||||
cork_dllist_init(&outbound_block_list_rules);
|
||||
|
||||
struct ip_set *list_ipv4 = &black_list_ipv4;
|
||||
struct ip_set *list_ipv6 = &black_list_ipv6;
|
||||
struct cork_dllist *rules = &black_list_rules;
|
||||
|
||||
FILE *f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
LOGE("Invalid acl path.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char buf[257];
|
||||
while (!feof(f))
|
||||
if (fgets(buf, 256, f)) {
|
||||
// Trim the newline
|
||||
int len = strlen(buf);
|
||||
if (len > 0 && buf[len - 1] == '\n') {
|
||||
buf[len - 1] = '\0';
|
||||
}
|
||||
|
||||
char *line = trimwhitespace(buf);
|
||||
|
||||
// Skip comments
|
||||
if (line[0] == '#') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strlen(line) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(line, "[outbound_block_list]") == 0) {
|
||||
list_ipv4 = &outbound_block_list_ipv4;
|
||||
list_ipv6 = &outbound_block_list_ipv6;
|
||||
rules = &outbound_block_list_rules;
|
||||
continue;
|
||||
} else if (strcmp(line, "[black_list]") == 0
|
||||
|| strcmp(line, "[bypass_list]") == 0) {
|
||||
list_ipv4 = &black_list_ipv4;
|
||||
list_ipv6 = &black_list_ipv6;
|
||||
rules = &black_list_rules;
|
||||
continue;
|
||||
} else if (strcmp(line, "[white_list]") == 0
|
||||
|| strcmp(line, "[proxy_list]") == 0) {
|
||||
list_ipv4 = &white_list_ipv4;
|
||||
list_ipv6 = &white_list_ipv6;
|
||||
rules = &white_list_rules;
|
||||
continue;
|
||||
} else if (strcmp(line, "[reject_all]") == 0
|
||||
|| strcmp(line, "[bypass_all]") == 0) {
|
||||
acl_mode = WHITE_LIST;
|
||||
continue;
|
||||
} else if (strcmp(line, "[accept_all]") == 0
|
||||
|| strcmp(line, "[proxy_all]") == 0) {
|
||||
acl_mode = BLACK_LIST;
|
||||
continue;
|
||||
}
|
||||
|
||||
char host[257];
|
||||
int cidr;
|
||||
parse_addr_cidr(line, host, &cidr);
|
||||
|
||||
struct cork_ip addr;
|
||||
int err = cork_ip_init(&addr, host);
|
||||
if (!err) {
|
||||
if (addr.version == 4) {
|
||||
if (cidr >= 0) {
|
||||
ipset_ipv4_add_network(list_ipv4, &(addr.ip.v4), cidr);
|
||||
} else {
|
||||
ipset_ipv4_add(list_ipv4, &(addr.ip.v4));
|
||||
}
|
||||
} else if (addr.version == 6) {
|
||||
if (cidr >= 0) {
|
||||
ipset_ipv6_add_network(list_ipv6, &(addr.ip.v6), cidr);
|
||||
} else {
|
||||
ipset_ipv6_add(list_ipv6, &(addr.ip.v6));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rule_t *rule = new_rule();
|
||||
accept_rule_arg(rule, line);
|
||||
init_rule(rule);
|
||||
add_rule(rules, rule);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
free_rules(struct cork_dllist *rules)
|
||||
{
|
||||
struct cork_dllist_item *iter;
|
||||
while ((iter = cork_dllist_head(rules)) != NULL) {
|
||||
rule_t *rule = cork_container_of(iter, rule_t, entries);
|
||||
remove_rule(rule);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
free_acl(void)
|
||||
{
|
||||
ipset_done(&black_list_ipv4);
|
||||
ipset_done(&black_list_ipv6);
|
||||
ipset_done(&white_list_ipv4);
|
||||
ipset_done(&white_list_ipv6);
|
||||
|
||||
free_rules(&black_list_rules);
|
||||
free_rules(&white_list_rules);
|
||||
}
|
||||
|
||||
int
|
||||
get_acl_mode(void)
|
||||
{
|
||||
return acl_mode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0, if not match.
|
||||
* Return 1, if match black list.
|
||||
* Return -1, if match white list.
|
||||
*/
|
||||
int
|
||||
acl_match_host(const char *host)
|
||||
{
|
||||
struct cork_ip addr;
|
||||
int ret = 0;
|
||||
int err = cork_ip_init(&addr, host);
|
||||
|
||||
if (err) {
|
||||
int host_len = strlen(host);
|
||||
if (lookup_rule(&black_list_rules, host, host_len) != NULL)
|
||||
ret = 1;
|
||||
else if (lookup_rule(&white_list_rules, host, host_len) != NULL)
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (addr.version == 4) {
|
||||
if (ipset_contains_ipv4(&black_list_ipv4, &(addr.ip.v4)))
|
||||
ret = 1;
|
||||
else if (ipset_contains_ipv4(&white_list_ipv4, &(addr.ip.v4)))
|
||||
ret = -1;
|
||||
} else if (addr.version == 6) {
|
||||
if (ipset_contains_ipv6(&black_list_ipv6, &(addr.ip.v6)))
|
||||
ret = 1;
|
||||
else if (ipset_contains_ipv6(&white_list_ipv6, &(addr.ip.v6)))
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
acl_add_ip(const char *ip)
|
||||
{
|
||||
struct cork_ip addr;
|
||||
int err = cork_ip_init(&addr, ip);
|
||||
if (err) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (addr.version == 4) {
|
||||
ipset_ipv4_add(&black_list_ipv4, &(addr.ip.v4));
|
||||
} else if (addr.version == 6) {
|
||||
ipset_ipv6_add(&black_list_ipv6, &(addr.ip.v6));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
acl_remove_ip(const char *ip)
|
||||
{
|
||||
struct cork_ip addr;
|
||||
int err = cork_ip_init(&addr, ip);
|
||||
if (err) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (addr.version == 4) {
|
||||
ipset_ipv4_remove(&black_list_ipv4, &(addr.ip.v4));
|
||||
} else if (addr.version == 6) {
|
||||
ipset_ipv6_remove(&black_list_ipv6, &(addr.ip.v6));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0, if not match.
|
||||
* Return 1, if match black list.
|
||||
*/
|
||||
int
|
||||
outbound_block_match_host(const char *host)
|
||||
{
|
||||
struct cork_ip addr;
|
||||
int ret = 0;
|
||||
int err = cork_ip_init(&addr, host);
|
||||
|
||||
if (err) {
|
||||
int host_len = strlen(host);
|
||||
if (lookup_rule(&outbound_block_list_rules, host, host_len) != NULL)
|
||||
ret = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (addr.version == 4) {
|
||||
if (ipset_contains_ipv4(&outbound_block_list_ipv4, &(addr.ip.v4)))
|
||||
ret = 1;
|
||||
} else if (addr.version == 6) {
|
||||
if (ipset_contains_ipv6(&outbound_block_list_ipv6, &(addr.ip.v6)))
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
53
shadowsocksr-libev/src/server/acl.h
Normal file
53
shadowsocksr-libev/src/server/acl.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* acl.h - Define the ACL interface
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* This file is part of the shadowsocks-libev.
|
||||
*
|
||||
* shadowsocks-libev is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* shadowsocks-libev is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with shadowsocks-libev; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ACL_H
|
||||
#define _ACL_H
|
||||
|
||||
#define BLACK_LIST 0
|
||||
#define WHITE_LIST 1
|
||||
|
||||
#define MAX_TRIES 64
|
||||
#define MALICIOUS 8
|
||||
#define SUSPICIOUS 4
|
||||
#define BAD 2
|
||||
#define MALFORMED 1
|
||||
|
||||
int init_acl(const char *path);
|
||||
void free_acl(void);
|
||||
void clear_block_list(void);
|
||||
|
||||
int acl_match_host(const char *ip);
|
||||
int acl_add_ip(const char *ip);
|
||||
int acl_remove_ip(const char *ip);
|
||||
|
||||
int get_acl_mode(void);
|
||||
|
||||
void init_block_list(int firewall);
|
||||
void free_block_list();
|
||||
int check_block_list(char *addr);
|
||||
int update_block_list(char *addr, int err_level);
|
||||
int remove_from_block_list(char *addr);
|
||||
|
||||
int outbound_block_match_host(const char *host);
|
||||
|
||||
#endif // _ACL_H
|
993
shadowsocksr-libev/src/server/auth.c
Normal file
993
shadowsocksr-libev/src/server/auth.c
Normal file
@ -0,0 +1,993 @@
|
||||
|
||||
#include "auth.h"
|
||||
|
||||
static int auth_simple_pack_unit_size = 2000;
|
||||
typedef int (*hmac_with_key_func)(char *auth, char *msg, int msg_len, uint8_t *auth_key, int key_len);
|
||||
typedef int (*hash_func)(char *auth, char *msg, int msg_len);
|
||||
|
||||
typedef struct auth_simple_global_data {
|
||||
uint8_t local_client_id[8];
|
||||
uint32_t connection_id;
|
||||
}auth_simple_global_data;
|
||||
|
||||
typedef struct auth_simple_local_data {
|
||||
int has_sent_header;
|
||||
char * recv_buffer;
|
||||
int recv_buffer_size;
|
||||
uint32_t recv_id;
|
||||
uint32_t pack_id;
|
||||
char * salt;
|
||||
uint8_t * user_key;
|
||||
char uid[4];
|
||||
int user_key_len;
|
||||
hmac_with_key_func hmac;
|
||||
hash_func hash;
|
||||
int hash_len;
|
||||
}auth_simple_local_data;
|
||||
|
||||
void auth_simple_local_data_init(auth_simple_local_data* local) {
|
||||
local->has_sent_header = 0;
|
||||
local->recv_buffer = (char*)malloc(16384);
|
||||
local->recv_buffer_size = 0;
|
||||
local->recv_id = 1;
|
||||
local->pack_id = 1;
|
||||
local->salt = "";
|
||||
local->user_key = 0;
|
||||
local->user_key_len = 0;
|
||||
local->hmac = 0;
|
||||
local->hash = 0;
|
||||
local->hash_len = 0;
|
||||
local->salt = "";
|
||||
}
|
||||
|
||||
void * auth_simple_init_data() {
|
||||
auth_simple_global_data *global = (auth_simple_global_data*)malloc(sizeof(auth_simple_global_data));
|
||||
rand_bytes(global->local_client_id, 8);
|
||||
rand_bytes((uint8_t*)&global->connection_id, 4);
|
||||
global->connection_id &= 0xFFFFFF;
|
||||
return global;
|
||||
}
|
||||
|
||||
obfs * auth_simple_new_obfs() {
|
||||
obfs * self = new_obfs();
|
||||
self->l_data = malloc(sizeof(auth_simple_local_data));
|
||||
auth_simple_local_data_init((auth_simple_local_data*)self->l_data);
|
||||
return self;
|
||||
}
|
||||
|
||||
obfs * auth_aes128_md5_new_obfs() {
|
||||
obfs * self = new_obfs();
|
||||
self->l_data = malloc(sizeof(auth_simple_local_data));
|
||||
auth_simple_local_data_init((auth_simple_local_data*)self->l_data);
|
||||
((auth_simple_local_data*)self->l_data)->hmac = ss_md5_hmac_with_key;
|
||||
((auth_simple_local_data*)self->l_data)->hash = ss_md5_hash_func;
|
||||
((auth_simple_local_data*)self->l_data)->hash_len = 16;
|
||||
((auth_simple_local_data*)self->l_data)->salt = "auth_aes128_md5";
|
||||
return self;
|
||||
}
|
||||
|
||||
obfs * auth_aes128_sha1_new_obfs() {
|
||||
obfs * self = new_obfs();
|
||||
self->l_data = malloc(sizeof(auth_simple_local_data));
|
||||
auth_simple_local_data_init((auth_simple_local_data*)self->l_data);
|
||||
((auth_simple_local_data*)self->l_data)->hmac = ss_sha1_hmac_with_key;
|
||||
((auth_simple_local_data*)self->l_data)->hash = ss_sha1_hash_func;
|
||||
((auth_simple_local_data*)self->l_data)->hash_len = 20;
|
||||
((auth_simple_local_data*)self->l_data)->salt = "auth_aes128_sha1";
|
||||
return self;
|
||||
}
|
||||
|
||||
void auth_simple_dispose(obfs *self) {
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
if (local->recv_buffer != NULL) {
|
||||
free(local->recv_buffer);
|
||||
local->recv_buffer = NULL;
|
||||
}
|
||||
if (local->user_key != NULL) {
|
||||
free(local->user_key);
|
||||
local->user_key = NULL;
|
||||
}
|
||||
free(local);
|
||||
self->l_data = NULL;
|
||||
dispose_obfs(self);
|
||||
}
|
||||
|
||||
int auth_simple_pack_data(char *data, int datalength, char *outdata) {
|
||||
unsigned char rand_len = (xorshift128plus() & 0xF) + 1;
|
||||
int out_size = rand_len + datalength + 6;
|
||||
outdata[0] = out_size >> 8;
|
||||
outdata[1] = out_size;
|
||||
outdata[2] = rand_len;
|
||||
memmove(outdata + rand_len + 2, data, datalength);
|
||||
fillcrc32((unsigned char *)outdata, out_size);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
void memintcopy_lt(void *mem, uint32_t val) {
|
||||
((uint8_t *)mem)[0] = val;
|
||||
((uint8_t *)mem)[1] = val >> 8;
|
||||
((uint8_t *)mem)[2] = val >> 16;
|
||||
((uint8_t *)mem)[3] = val >> 24;
|
||||
}
|
||||
|
||||
int auth_simple_pack_auth_data(auth_simple_global_data *global, char *data, int datalength, char *outdata) {
|
||||
unsigned char rand_len = (xorshift128plus() & 0xF) + 1;
|
||||
int out_size = rand_len + datalength + 6 + 12;
|
||||
outdata[0] = out_size >> 8;
|
||||
outdata[1] = out_size;
|
||||
outdata[2] = rand_len;
|
||||
++global->connection_id;
|
||||
if (global->connection_id > 0xFF000000) {
|
||||
rand_bytes(global->local_client_id, 8);
|
||||
rand_bytes((uint8_t*)&global->connection_id, 4);
|
||||
global->connection_id &= 0xFFFFFF;
|
||||
}
|
||||
time_t t = time(NULL);
|
||||
memintcopy_lt(outdata + rand_len + 2, t);
|
||||
memmove(outdata + rand_len + 2 + 4, global->local_client_id, 4);
|
||||
memintcopy_lt(outdata + rand_len + 2 + 8, global->connection_id);
|
||||
memmove(outdata + rand_len + 2 + 12, data, datalength);
|
||||
fillcrc32((unsigned char *)outdata, out_size);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_simple_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
char * out_buffer = (char*)malloc(datalength * 2 + 64);
|
||||
char * buffer = out_buffer;
|
||||
char * data = plaindata;
|
||||
int len = datalength;
|
||||
int pack_len;
|
||||
if (len > 0 && local->has_sent_header == 0) {
|
||||
int head_size = get_head_size(plaindata, datalength, 30);
|
||||
if (head_size > datalength)
|
||||
head_size = datalength;
|
||||
pack_len = auth_simple_pack_auth_data((auth_simple_global_data *)self->server.g_data, data, head_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += head_size;
|
||||
len -= head_size;
|
||||
local->has_sent_header = 1;
|
||||
}
|
||||
while ( len > auth_simple_pack_unit_size ) {
|
||||
pack_len = auth_simple_pack_data(data, auth_simple_pack_unit_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += auth_simple_pack_unit_size;
|
||||
len -= auth_simple_pack_unit_size;
|
||||
}
|
||||
if (len > 0) {
|
||||
pack_len = auth_simple_pack_data(data, len, buffer);
|
||||
buffer += pack_len;
|
||||
}
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int auth_simple_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
|
||||
if (local->recv_buffer_size + datalength > 16384)
|
||||
return -1;
|
||||
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
|
||||
char * out_buffer = (char*)malloc(local->recv_buffer_size);
|
||||
char * buffer = out_buffer;
|
||||
while (local->recv_buffer_size > 2) {
|
||||
int length = ((int)recv_buffer[0] << 8) | recv_buffer[1];
|
||||
if (length >= 8192 || length < 7) {
|
||||
free(out_buffer);
|
||||
local->recv_buffer_size = 0;
|
||||
return -1;
|
||||
}
|
||||
if (length > local->recv_buffer_size)
|
||||
break;
|
||||
|
||||
int crc = crc32((unsigned char*)recv_buffer, length);
|
||||
if (crc != -1) {
|
||||
free(out_buffer);
|
||||
local->recv_buffer_size = 0;
|
||||
return -1;
|
||||
}
|
||||
int data_size = length - recv_buffer[2] - 6;
|
||||
memmove(buffer, recv_buffer + 2 + recv_buffer[2], data_size);
|
||||
buffer += data_size;
|
||||
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
|
||||
}
|
||||
int len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
int auth_sha1_pack_data(char *data, int datalength, char *outdata) {
|
||||
unsigned char rand_len = (xorshift128plus() & 0xF) + 1;
|
||||
int out_size = rand_len + datalength + 6;
|
||||
outdata[0] = out_size >> 8;
|
||||
outdata[1] = out_size;
|
||||
outdata[2] = rand_len;
|
||||
memmove(outdata + rand_len + 2, data, datalength);
|
||||
filladler32((unsigned char *)outdata, out_size);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_sha1_pack_auth_data(auth_simple_global_data *global, server_info *server, char *data, int datalength, char *outdata) {
|
||||
unsigned char rand_len = (xorshift128plus() & 0x7F) + 1;
|
||||
int data_offset = rand_len + 4 + 2;
|
||||
int out_size = data_offset + datalength + 12 + OBFS_HMAC_SHA1_LEN;
|
||||
fillcrc32to((unsigned char *)server->key, server->key_len, (unsigned char *)outdata);
|
||||
outdata[4] = out_size >> 8;
|
||||
outdata[5] = out_size;
|
||||
outdata[6] = rand_len;
|
||||
++global->connection_id;
|
||||
if (global->connection_id > 0xFF000000) {
|
||||
rand_bytes(global->local_client_id, 8);
|
||||
rand_bytes((uint8_t*)&global->connection_id, 4);
|
||||
global->connection_id &= 0xFFFFFF;
|
||||
}
|
||||
time_t t = time(NULL);
|
||||
memintcopy_lt(outdata + data_offset, t);
|
||||
memmove(outdata + data_offset + 4, global->local_client_id, 4);
|
||||
memintcopy_lt(outdata + data_offset + 8, global->connection_id);
|
||||
memmove(outdata + data_offset + 12, data, datalength);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
ss_sha1_hmac(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, server->iv);
|
||||
memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
char * out_buffer = (char*)malloc(datalength * 2 + 256);
|
||||
char * buffer = out_buffer;
|
||||
char * data = plaindata;
|
||||
int len = datalength;
|
||||
int pack_len;
|
||||
if (len > 0 && local->has_sent_header == 0) {
|
||||
int head_size = get_head_size(plaindata, datalength, 30);
|
||||
if (head_size > datalength)
|
||||
head_size = datalength;
|
||||
pack_len = auth_sha1_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, data, head_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += head_size;
|
||||
len -= head_size;
|
||||
local->has_sent_header = 1;
|
||||
}
|
||||
while ( len > auth_simple_pack_unit_size ) {
|
||||
pack_len = auth_sha1_pack_data(data, auth_simple_pack_unit_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += auth_simple_pack_unit_size;
|
||||
len -= auth_simple_pack_unit_size;
|
||||
}
|
||||
if (len > 0) {
|
||||
pack_len = auth_sha1_pack_data(data, len, buffer);
|
||||
buffer += pack_len;
|
||||
}
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int auth_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
|
||||
if (local->recv_buffer_size + datalength > 16384)
|
||||
return -1;
|
||||
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
|
||||
char * out_buffer = (char*)malloc(local->recv_buffer_size);
|
||||
char * buffer = out_buffer;
|
||||
while (local->recv_buffer_size > 2) {
|
||||
int length = ((int)recv_buffer[0] << 8) | recv_buffer[1];
|
||||
if (length >= 8192 || length < 7) {
|
||||
free(out_buffer);
|
||||
local->recv_buffer_size = 0;
|
||||
return -1;
|
||||
}
|
||||
if (length > local->recv_buffer_size)
|
||||
break;
|
||||
|
||||
if (checkadler32((unsigned char*)recv_buffer, length) == 0) {
|
||||
free(out_buffer);
|
||||
local->recv_buffer_size = 0;
|
||||
return -1;
|
||||
}
|
||||
int pos = recv_buffer[2] + 2;
|
||||
int data_size = length - pos - 4;
|
||||
memmove(buffer, recv_buffer + pos, data_size);
|
||||
buffer += data_size;
|
||||
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
|
||||
}
|
||||
int len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int auth_sha1_v2_pack_data(char *data, int datalength, char *outdata) {
|
||||
unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1;
|
||||
int out_size = rand_len + datalength + 6;
|
||||
outdata[0] = out_size >> 8;
|
||||
outdata[1] = out_size;
|
||||
if (rand_len < 128)
|
||||
{
|
||||
outdata[2] = rand_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
outdata[2] = 0xFF;
|
||||
outdata[3] = rand_len >> 8;
|
||||
outdata[4] = rand_len;
|
||||
}
|
||||
memmove(outdata + rand_len + 2, data, datalength);
|
||||
filladler32((unsigned char *)outdata, out_size);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_sha1_v2_pack_auth_data(auth_simple_global_data *global, server_info *server, char *data, int datalength, char *outdata) {
|
||||
unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1;
|
||||
int data_offset = rand_len + 4 + 2;
|
||||
int out_size = data_offset + datalength + 12 + OBFS_HMAC_SHA1_LEN;
|
||||
const char* salt = "auth_sha1_v2";
|
||||
int salt_len = strlen(salt);
|
||||
unsigned char *crc_salt = (unsigned char*)malloc(salt_len + server->key_len);
|
||||
memcpy(crc_salt, salt, salt_len);
|
||||
memcpy(crc_salt + salt_len, server->key, server->key_len);
|
||||
fillcrc32to(crc_salt, salt_len + server->key_len, (unsigned char *)outdata);
|
||||
free(crc_salt);
|
||||
outdata[4] = out_size >> 8;
|
||||
outdata[5] = out_size;
|
||||
if (rand_len < 128)
|
||||
{
|
||||
outdata[6] = rand_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
outdata[6] = 0xFF;
|
||||
outdata[7] = rand_len >> 8;
|
||||
outdata[8] = rand_len;
|
||||
}
|
||||
++global->connection_id;
|
||||
if (global->connection_id > 0xFF000000) {
|
||||
rand_bytes(global->local_client_id, 8);
|
||||
rand_bytes((uint8_t*)&global->connection_id, 4);
|
||||
global->connection_id &= 0xFFFFFF;
|
||||
}
|
||||
memmove(outdata + data_offset, global->local_client_id, 8);
|
||||
memintcopy_lt(outdata + data_offset + 8, global->connection_id);
|
||||
memmove(outdata + data_offset + 12, data, datalength);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
ss_sha1_hmac(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, server->iv);
|
||||
memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_sha1_v2_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
char * out_buffer = (char*)malloc(datalength * 2 + 4096);
|
||||
char * buffer = out_buffer;
|
||||
char * data = plaindata;
|
||||
int len = datalength;
|
||||
int pack_len;
|
||||
if (len > 0 && local->has_sent_header == 0) {
|
||||
int head_size = get_head_size(plaindata, datalength, 30);
|
||||
if (head_size > datalength)
|
||||
head_size = datalength;
|
||||
pack_len = auth_sha1_v2_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, data, head_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += head_size;
|
||||
len -= head_size;
|
||||
local->has_sent_header = 1;
|
||||
}
|
||||
while ( len > auth_simple_pack_unit_size ) {
|
||||
pack_len = auth_sha1_v2_pack_data(data, auth_simple_pack_unit_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += auth_simple_pack_unit_size;
|
||||
len -= auth_simple_pack_unit_size;
|
||||
}
|
||||
if (len > 0) {
|
||||
pack_len = auth_sha1_v2_pack_data(data, len, buffer);
|
||||
buffer += pack_len;
|
||||
}
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int auth_sha1_v2_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
|
||||
if (local->recv_buffer_size + datalength > 16384)
|
||||
return -1;
|
||||
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
|
||||
char * out_buffer = (char*)malloc(local->recv_buffer_size);
|
||||
char * buffer = out_buffer;
|
||||
char error = 0;
|
||||
while (local->recv_buffer_size > 2) {
|
||||
int length = ((int)recv_buffer[0] << 8) | recv_buffer[1];
|
||||
if (length >= 8192 || length < 7) {
|
||||
local->recv_buffer_size = 0;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if (length > local->recv_buffer_size)
|
||||
break;
|
||||
|
||||
if (checkadler32((unsigned char*)recv_buffer, length) == 0) {
|
||||
local->recv_buffer_size = 0;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
int pos = recv_buffer[2];
|
||||
if (pos < 255)
|
||||
{
|
||||
pos += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = ((recv_buffer[3] << 8) | recv_buffer[4]) + 2;
|
||||
}
|
||||
int data_size = length - pos - 4;
|
||||
memmove(buffer, recv_buffer + pos, data_size);
|
||||
buffer += data_size;
|
||||
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
|
||||
}
|
||||
int len;
|
||||
if (error == 0) {
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
} else {
|
||||
len = -1;
|
||||
}
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int auth_sha1_v4_pack_data(char *data, int datalength, char *outdata) {
|
||||
unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1;
|
||||
int out_size = rand_len + datalength + 8;
|
||||
outdata[0] = out_size >> 8;
|
||||
outdata[1] = out_size;
|
||||
uint32_t crc_val = crc32((unsigned char*)outdata, 2);
|
||||
outdata[2] = crc_val;
|
||||
outdata[3] = crc_val >> 8;
|
||||
if (rand_len < 128)
|
||||
{
|
||||
outdata[4] = rand_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
outdata[4] = 0xFF;
|
||||
outdata[5] = rand_len >> 8;
|
||||
outdata[6] = rand_len;
|
||||
}
|
||||
memmove(outdata + rand_len + 4, data, datalength);
|
||||
filladler32((unsigned char *)outdata, out_size);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_sha1_v4_pack_auth_data(auth_simple_global_data *global, server_info *server, char *data, int datalength, char *outdata) {
|
||||
unsigned int rand_len = (datalength > 1300 ? 0 : datalength > 400 ? (xorshift128plus() & 0x7F) : (xorshift128plus() & 0x3FF)) + 1;
|
||||
int data_offset = rand_len + 4 + 2;
|
||||
int out_size = data_offset + datalength + 12 + OBFS_HMAC_SHA1_LEN;
|
||||
const char* salt = "auth_sha1_v4";
|
||||
int salt_len = strlen(salt);
|
||||
unsigned char *crc_salt = (unsigned char*)malloc(salt_len + server->key_len + 2);
|
||||
crc_salt[0] = outdata[0] = out_size >> 8;
|
||||
crc_salt[1] = outdata[1] = out_size;
|
||||
|
||||
memcpy(crc_salt + 2, salt, salt_len);
|
||||
memcpy(crc_salt + salt_len + 2, server->key, server->key_len);
|
||||
fillcrc32to(crc_salt, salt_len + server->key_len + 2, (unsigned char *)outdata + 2);
|
||||
free(crc_salt);
|
||||
if (rand_len < 128)
|
||||
{
|
||||
outdata[6] = rand_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
outdata[6] = 0xFF;
|
||||
outdata[7] = rand_len >> 8;
|
||||
outdata[8] = rand_len;
|
||||
}
|
||||
++global->connection_id;
|
||||
if (global->connection_id > 0xFF000000) {
|
||||
rand_bytes(global->local_client_id, 8);
|
||||
rand_bytes((uint8_t*)&global->connection_id, 4);
|
||||
global->connection_id &= 0xFFFFFF;
|
||||
}
|
||||
time_t t = time(NULL);
|
||||
memintcopy_lt(outdata + data_offset, t);
|
||||
memmove(outdata + data_offset + 4, global->local_client_id, 4);
|
||||
memintcopy_lt(outdata + data_offset + 8, global->connection_id);
|
||||
memmove(outdata + data_offset + 12, data, datalength);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
ss_sha1_hmac(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, server->iv);
|
||||
memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_sha1_v4_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
char * out_buffer = (char*)malloc(datalength * 2 + 4096);
|
||||
char * buffer = out_buffer;
|
||||
char * data = plaindata;
|
||||
int len = datalength;
|
||||
int pack_len;
|
||||
if (len > 0 && local->has_sent_header == 0) {
|
||||
int head_size = get_head_size(plaindata, datalength, 30);
|
||||
if (head_size > datalength)
|
||||
head_size = datalength;
|
||||
pack_len = auth_sha1_v4_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, data, head_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += head_size;
|
||||
len -= head_size;
|
||||
local->has_sent_header = 1;
|
||||
}
|
||||
while ( len > auth_simple_pack_unit_size ) {
|
||||
pack_len = auth_sha1_v4_pack_data(data, auth_simple_pack_unit_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += auth_simple_pack_unit_size;
|
||||
len -= auth_simple_pack_unit_size;
|
||||
}
|
||||
if (len > 0) {
|
||||
pack_len = auth_sha1_v4_pack_data(data, len, buffer);
|
||||
buffer += pack_len;
|
||||
}
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int auth_sha1_v4_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
|
||||
if (local->recv_buffer_size + datalength > 16384)
|
||||
return -1;
|
||||
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
|
||||
char * out_buffer = (char*)malloc(local->recv_buffer_size);
|
||||
char * buffer = out_buffer;
|
||||
char error = 0;
|
||||
while (local->recv_buffer_size > 4) {
|
||||
uint32_t crc_val = crc32((unsigned char*)recv_buffer, 2);
|
||||
if ((((uint32_t)recv_buffer[3] << 8) | recv_buffer[2]) != (crc_val & 0xffff)) {
|
||||
local->recv_buffer_size = 0;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
int length = ((int)recv_buffer[0] << 8) | recv_buffer[1];
|
||||
if (length >= 8192 || length < 7) {
|
||||
local->recv_buffer_size = 0;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if (length > local->recv_buffer_size)
|
||||
break;
|
||||
|
||||
if (checkadler32((unsigned char*)recv_buffer, length) == 0) {
|
||||
local->recv_buffer_size = 0;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
int pos = recv_buffer[4];
|
||||
if (pos < 255)
|
||||
{
|
||||
pos += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = (((int)recv_buffer[5] << 8) | recv_buffer[6]) + 4;
|
||||
}
|
||||
int data_size = length - pos - 4;
|
||||
memmove(buffer, recv_buffer + pos, data_size);
|
||||
buffer += data_size;
|
||||
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
|
||||
}
|
||||
int len;
|
||||
if (error == 0) {
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
} else {
|
||||
len = -1;
|
||||
}
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
int auth_aes128_sha1_pack_data(char *data, int datalength, char *outdata, auth_simple_local_data *local, server_info *server) {
|
||||
unsigned int rand_len = (datalength > 1200 ? 0 : local->pack_id > 4 ? (xorshift128plus() & 0x20) : datalength > 900 ? (xorshift128plus() & 0x80) : (xorshift128plus() & 0x200)) + 1;
|
||||
int out_size = rand_len + datalength + 8;
|
||||
memcpy(outdata + rand_len + 4, data, datalength);
|
||||
outdata[0] = out_size;
|
||||
outdata[1] = out_size >> 8;
|
||||
uint8_t key_len = local->user_key_len + 4;
|
||||
uint8_t *key = (uint8_t*)malloc(key_len);
|
||||
memcpy(key, local->user_key, local->user_key_len);
|
||||
memintcopy_lt(key + key_len - 4, local->pack_id);
|
||||
|
||||
{
|
||||
uint8_t rnd_data[rand_len];
|
||||
rand_bytes(rnd_data, rand_len);
|
||||
memcpy(outdata + 4, rnd_data, rand_len);
|
||||
}
|
||||
|
||||
{
|
||||
char hash[20];
|
||||
local->hmac(hash, outdata, 2, key, key_len);
|
||||
memcpy(outdata + 2, hash, 2);
|
||||
}
|
||||
|
||||
if (rand_len < 128)
|
||||
{
|
||||
outdata[4] = rand_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
outdata[4] = 0xFF;
|
||||
outdata[5] = rand_len;
|
||||
outdata[6] = rand_len >> 8;
|
||||
}
|
||||
++local->pack_id;
|
||||
|
||||
{
|
||||
char hash[20];
|
||||
local->hmac(hash, outdata, out_size - 4, key, key_len);
|
||||
memcpy(outdata + out_size - 4, hash, 4);
|
||||
}
|
||||
free(key);
|
||||
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_aes128_sha1_pack_auth_data(auth_simple_global_data *global, server_info *server, auth_simple_local_data *local, char *data, int datalength, char *outdata) {
|
||||
unsigned int rand_len = (datalength > 400 ? (xorshift128plus() & 0x200) : (xorshift128plus() & 0x400));
|
||||
int data_offset = rand_len + 16 + 4 + 4 + 7;
|
||||
int out_size = data_offset + datalength + 4;
|
||||
|
||||
char encrypt[24];
|
||||
char encrypt_data[16];
|
||||
|
||||
uint8_t *key = (uint8_t*)malloc(server->iv_len + server->key_len);
|
||||
uint8_t key_len = server->iv_len + server->key_len;
|
||||
memcpy(key, server->iv, server->iv_len);
|
||||
memcpy(key + server->iv_len, server->key, server->key_len);
|
||||
|
||||
{
|
||||
uint8_t rnd_data[rand_len];
|
||||
rand_bytes(rnd_data, rand_len);
|
||||
memcpy(outdata + data_offset - rand_len, rnd_data, rand_len);
|
||||
}
|
||||
|
||||
++global->connection_id;
|
||||
if (global->connection_id > 0xFF000000) {
|
||||
rand_bytes(global->local_client_id, 8);
|
||||
rand_bytes((uint8_t*)&global->connection_id, 4);
|
||||
global->connection_id &= 0xFFFFFF;
|
||||
}
|
||||
time_t t = time(NULL);
|
||||
memintcopy_lt(encrypt, t);
|
||||
memcpy(encrypt + 4, global->local_client_id, 4);
|
||||
memintcopy_lt(encrypt + 8, global->connection_id);
|
||||
encrypt[12] = out_size;
|
||||
encrypt[13] = out_size >> 8;
|
||||
encrypt[14] = rand_len;
|
||||
encrypt[15] = rand_len >> 8;
|
||||
|
||||
{
|
||||
|
||||
if (local->user_key == NULL) {
|
||||
if(server->param != NULL && server->param[0] != 0) {
|
||||
char *param = server->param;
|
||||
char *delim = strchr(param, ':');
|
||||
if(delim != NULL) {
|
||||
char uid_str[16] = {};
|
||||
strncpy(uid_str, param, delim - param);
|
||||
char key_str[128];
|
||||
strcpy(key_str, delim + 1);
|
||||
long uid_long = strtol(uid_str, NULL, 10);
|
||||
memintcopy_lt(local->uid, uid_long);
|
||||
|
||||
char hash[21] = {0};
|
||||
local->hash(hash, key_str, strlen(key_str));
|
||||
|
||||
local->user_key_len = local->hash_len;
|
||||
local->user_key = (uint8_t*)malloc(local->user_key_len);
|
||||
memcpy(local->user_key, hash, local->hash_len);
|
||||
}
|
||||
}
|
||||
if (local->user_key == NULL) {
|
||||
rand_bytes((uint8_t *)local->uid, 4);
|
||||
|
||||
local->user_key_len = server->key_len;
|
||||
local->user_key = (uint8_t*)malloc(local->user_key_len);
|
||||
memcpy(local->user_key, server->key, local->user_key_len);
|
||||
}
|
||||
}
|
||||
|
||||
char encrypt_key_base64[256] = {0};
|
||||
unsigned char encrypt_key[local->user_key_len];
|
||||
memcpy(encrypt_key, local->user_key, local->user_key_len);
|
||||
base64_encode(encrypt_key, local->user_key_len, encrypt_key_base64);
|
||||
|
||||
int base64_len;
|
||||
base64_len = (local->user_key_len + 2) / 3 * 4;
|
||||
memcpy(encrypt_key_base64 + base64_len, local->salt, strlen(local->salt));
|
||||
|
||||
char enc_key[16];
|
||||
int enc_key_len = base64_len + strlen(local->salt);
|
||||
bytes_to_key_with_size(encrypt_key_base64, enc_key_len, (uint8_t*)enc_key, 16);
|
||||
ss_aes_128_cbc(encrypt, encrypt_data, enc_key);
|
||||
memcpy(encrypt + 4, encrypt_data, 16);
|
||||
memcpy(encrypt, local->uid, 4);
|
||||
}
|
||||
|
||||
{
|
||||
char hash[20];
|
||||
local->hmac(hash, encrypt, 20, key, key_len);
|
||||
memcpy(encrypt + 20, hash, 4);
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t rnd[1];
|
||||
rand_bytes(rnd, 1);
|
||||
memcpy(outdata, rnd, 1);
|
||||
char hash[20];
|
||||
local->hmac(hash, (char *)rnd, 1, key, key_len);
|
||||
memcpy(outdata + 1, hash, 6);
|
||||
}
|
||||
|
||||
memcpy(outdata + 7, encrypt, 24);
|
||||
memcpy(outdata + data_offset, data, datalength);
|
||||
|
||||
{
|
||||
char hash[20];
|
||||
local->hmac(hash, outdata, out_size - 4, local->user_key, local->user_key_len);
|
||||
memmove(outdata + out_size - 4, hash, 4);
|
||||
}
|
||||
free(key);
|
||||
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int auth_aes128_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
char * out_buffer = (char*)malloc(datalength * 2 + 4096);
|
||||
char * buffer = out_buffer;
|
||||
char * data = plaindata;
|
||||
int len = datalength;
|
||||
int pack_len;
|
||||
if (len > 0 && local->has_sent_header == 0) {
|
||||
int head_size = 1200;
|
||||
if (head_size > datalength)
|
||||
head_size = datalength;
|
||||
pack_len = auth_aes128_sha1_pack_auth_data((auth_simple_global_data *)self->server.g_data, &self->server, local, data, head_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += head_size;
|
||||
len -= head_size;
|
||||
local->has_sent_header = 1;
|
||||
}
|
||||
while ( len > auth_simple_pack_unit_size ) {
|
||||
pack_len = auth_aes128_sha1_pack_data(data, auth_simple_pack_unit_size, buffer, local, &self->server);
|
||||
buffer += pack_len;
|
||||
data += auth_simple_pack_unit_size;
|
||||
len -= auth_simple_pack_unit_size;
|
||||
}
|
||||
if (len > 0) {
|
||||
pack_len = auth_aes128_sha1_pack_data(data, len, buffer, local, &self->server);
|
||||
buffer += pack_len;
|
||||
}
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int auth_aes128_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
//server_info *server = (server_info*)&self->server;
|
||||
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
|
||||
if (local->recv_buffer_size + datalength > 16384)
|
||||
return -1;
|
||||
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
|
||||
int key_len = local->user_key_len + 4;
|
||||
uint8_t *key = (uint8_t*)malloc(key_len);
|
||||
memcpy(key, local->user_key, local->user_key_len);
|
||||
|
||||
char * out_buffer = (char*)malloc(local->recv_buffer_size);
|
||||
char * buffer = out_buffer;
|
||||
char error = 0;
|
||||
while (local->recv_buffer_size > 4) {
|
||||
memintcopy_lt(key + key_len - 4, local->recv_id);
|
||||
|
||||
{
|
||||
char hash[20];
|
||||
local->hmac(hash, (char*)recv_buffer, 2, key, key_len);
|
||||
|
||||
if (memcmp(hash, recv_buffer + 2, 2)) {
|
||||
local->recv_buffer_size = 0;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int length = ((int)recv_buffer[1] << 8) + recv_buffer[0];
|
||||
if (length >= 8192 || length < 8) {
|
||||
local->recv_buffer_size = 0;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if (length > local->recv_buffer_size)
|
||||
break;
|
||||
|
||||
{
|
||||
char hash[20];
|
||||
local->hmac(hash, (char *)recv_buffer, length - 4, key, key_len);
|
||||
if (memcmp(hash, recv_buffer + length - 4, 4))
|
||||
{
|
||||
local->recv_buffer_size = 0;
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++local->recv_id;
|
||||
int pos = recv_buffer[4];
|
||||
if (pos < 255)
|
||||
{
|
||||
pos += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = (((int)recv_buffer[6] << 8) | recv_buffer[5]) + 4;
|
||||
}
|
||||
int data_size = length - pos - 4;
|
||||
memmove(buffer, recv_buffer + pos, data_size);
|
||||
buffer += data_size;
|
||||
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
|
||||
}
|
||||
int len;
|
||||
if (error == 0) {
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
} else {
|
||||
len = -1;
|
||||
}
|
||||
free(out_buffer);
|
||||
free(key);
|
||||
return len;
|
||||
}
|
||||
|
||||
int auth_aes128_sha1_client_udp_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
char * out_buffer = (char*)malloc(datalength + 8);
|
||||
|
||||
if (local->user_key == NULL) {
|
||||
if(self->server.param != NULL && self->server.param[0] != 0) {
|
||||
char *param = self->server.param;
|
||||
char *delim = strchr(param, ':');
|
||||
if(delim != NULL) {
|
||||
char uid_str[16] = {};
|
||||
strncpy(uid_str, param, delim - param);
|
||||
char key_str[128];
|
||||
strcpy(key_str, delim + 1);
|
||||
long uid_long = strtol(uid_str, NULL, 10);
|
||||
memintcopy_lt(local->uid, uid_long);
|
||||
|
||||
char hash[21] = {0};
|
||||
local->hash(hash, key_str, strlen(key_str));
|
||||
|
||||
local->user_key_len = local->hash_len;
|
||||
local->user_key = (uint8_t*)malloc(local->user_key_len);
|
||||
memcpy(local->user_key, hash, local->hash_len);
|
||||
}
|
||||
}
|
||||
if (local->user_key == NULL) {
|
||||
rand_bytes((uint8_t *)local->uid, 4);
|
||||
|
||||
local->user_key_len = self->server.key_len;
|
||||
local->user_key = (uint8_t*)malloc(local->user_key_len);
|
||||
memcpy(local->user_key, self->server.key, local->user_key_len);
|
||||
}
|
||||
}
|
||||
|
||||
int outlength = datalength + 8;
|
||||
memmove(out_buffer, plaindata, datalength);
|
||||
memmove(out_buffer + datalength, local->uid, 4);
|
||||
|
||||
{
|
||||
char hash[20];
|
||||
local->hmac(hash, out_buffer, outlength - 4, local->user_key, local->user_key_len);
|
||||
memmove(out_buffer + outlength - 4, hash, 4);
|
||||
}
|
||||
|
||||
if (*capacity < outlength) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = outlength * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, outlength);
|
||||
|
||||
free(out_buffer);
|
||||
return outlength;
|
||||
}
|
||||
|
||||
int auth_aes128_sha1_client_udp_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity) {
|
||||
if (datalength <= 4)
|
||||
return 0;
|
||||
|
||||
char *plaindata = *pplaindata;
|
||||
auth_simple_local_data *local = (auth_simple_local_data*)self->l_data;
|
||||
|
||||
char hash[20];
|
||||
local->hmac(hash, plaindata, datalength - 4, self->server.key, self->server.key_len);
|
||||
|
||||
if (memcmp(hash, plaindata + datalength - 4, 4))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return datalength - 4;
|
||||
}
|
30
shadowsocksr-libev/src/server/auth.h
Normal file
30
shadowsocksr-libev/src/server/auth.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* auth.h - Define shadowsocksR server's buffers and callbacks
|
||||
*
|
||||
* Copyright (C) 2015 - 2016, Break Wa11 <mmgac001@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _AUTH_H
|
||||
#define _AUTH_H
|
||||
|
||||
void * auth_simple_init_data();
|
||||
obfs * auth_simple_new_obfs();
|
||||
void auth_simple_dispose(obfs *self);
|
||||
|
||||
int auth_simple_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
int auth_simple_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
|
||||
|
||||
int auth_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
int auth_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
|
||||
int auth_sha1_v2_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
int auth_sha1_v2_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
|
||||
int auth_sha1_v4_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
int auth_sha1_v4_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
|
||||
int auth_aes128_sha1_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
int auth_aes128_sha1_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
|
||||
#endif // _AUTH_H
|
119
shadowsocksr-libev/src/server/base64.c
Normal file
119
shadowsocksr-libev/src/server/base64.c
Normal file
@ -0,0 +1,119 @@
|
||||
#include "base64.h"
|
||||
|
||||
/* BASE 64 encode table */
|
||||
static const char base64en[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
#define BASE64_PAD '='
|
||||
|
||||
#define BASE64DE_FIRST '+'
|
||||
#define BASE64DE_LAST 'z'
|
||||
|
||||
/* ASCII order for BASE 64 decode, -1 in unused character */
|
||||
static const signed char base64de[] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
/* '+', ',', '-', '.', '/', */
|
||||
-1, -1, -1, 62, -1, -1, -1, 63,
|
||||
/* '0', '1', '2', '3', '4', '5', '6', '7', */
|
||||
52, 53, 54, 55, 56, 57, 58, 59,
|
||||
/* '8', '9', ':', ';', '<', '=', '>', '?', */
|
||||
60, 61, -1, -1, -1, -1, -1, -1,
|
||||
/* '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', */
|
||||
-1, 0, 1, 2, 3, 4, 5, 6,
|
||||
/* 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', */
|
||||
7, 8, 9, 10, 11, 12, 13, 14,
|
||||
/* 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', */
|
||||
15, 16, 17, 18, 19, 20, 21, 22,
|
||||
/* 'X', 'Y', 'Z', '[', '\', ']', '^', '_', */
|
||||
23, 24, 25, -1, -1, -1, -1, -1,
|
||||
/* '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', */
|
||||
-1, 26, 27, 28, 29, 30, 31, 32,
|
||||
/* 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', */
|
||||
33, 34, 35, 36, 37, 38, 39, 40,
|
||||
/* 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', */
|
||||
41, 42, 43, 44, 45, 46, 47, 48,
|
||||
/* 'x', 'y', 'z', */
|
||||
49, 50, 51,
|
||||
};
|
||||
|
||||
int
|
||||
base64_encode(const unsigned char *in, unsigned int inlen, char *out)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = j = 0; i < inlen; i++) {
|
||||
int s = i % 3; /* from 6/gcd(6, 8) */
|
||||
|
||||
switch (s) {
|
||||
case 0:
|
||||
out[j++] = base64en[(in[i] >> 2) & 0x3F];
|
||||
continue;
|
||||
case 1:
|
||||
out[j++] = base64en[((in[i-1] & 0x3) << 4) + ((in[i] >> 4) & 0xF)];
|
||||
continue;
|
||||
case 2:
|
||||
out[j++] = base64en[((in[i-1] & 0xF) << 2) + ((in[i] >> 6) & 0x3)];
|
||||
out[j++] = base64en[in[i] & 0x3F];
|
||||
}
|
||||
}
|
||||
|
||||
/* move back */
|
||||
i -= 1;
|
||||
|
||||
/* check the last and add padding */
|
||||
if ((i % 3) == 0) {
|
||||
out[j++] = base64en[(in[i] & 0x3) << 4];
|
||||
out[j++] = BASE64_PAD;
|
||||
out[j++] = BASE64_PAD;
|
||||
} else if ((i % 3) == 1) {
|
||||
out[j++] = base64en[(in[i] & 0xF) << 2];
|
||||
out[j++] = BASE64_PAD;
|
||||
}
|
||||
|
||||
return BASE64_OK;
|
||||
}
|
||||
|
||||
int
|
||||
base64_decode(const char *in, unsigned int inlen, unsigned char *out)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = j = 0; i < inlen; i++) {
|
||||
int c;
|
||||
int s = i % 4; /* from 8/gcd(6, 8) */
|
||||
|
||||
if (in[i] == '=')
|
||||
return BASE64_OK;
|
||||
|
||||
if (in[i] < BASE64DE_FIRST || in[i] > BASE64DE_LAST ||
|
||||
(c = base64de[(int)in[i]]) == -1)
|
||||
return BASE64_INVALID;
|
||||
|
||||
switch (s) {
|
||||
case 0:
|
||||
out[j] = ((unsigned int)c << 2) & 0xFF;
|
||||
continue;
|
||||
case 1:
|
||||
out[j++] += ((unsigned int)c >> 4) & 0x3;
|
||||
|
||||
/* if not last char with padding */
|
||||
if (i < (inlen - 3) || in[inlen - 2] != '=')
|
||||
out[j] = ((unsigned int)c & 0xF) << 4;
|
||||
continue;
|
||||
case 2:
|
||||
out[j++] += ((unsigned int)c >> 2) & 0xF;
|
||||
|
||||
/* if not last char with padding */
|
||||
if (i < (inlen - 2) || in[inlen - 1] != '=')
|
||||
out[j] = ((unsigned int)c & 0x3) << 6;
|
||||
continue;
|
||||
case 3:
|
||||
out[j++] += (unsigned char)c;
|
||||
}
|
||||
}
|
||||
|
||||
return BASE64_OK;
|
||||
}
|
16
shadowsocksr-libev/src/server/base64.h
Normal file
16
shadowsocksr-libev/src/server/base64.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef __BASE64_H__
|
||||
#define __BASE64_H__
|
||||
|
||||
enum {BASE64_OK = 0, BASE64_INVALID};
|
||||
|
||||
#define BASE64_ENCODE_OUT_SIZE(s) (((s) + 2) / 3 * 4)
|
||||
#define BASE64_DECODE_OUT_SIZE(s) (((s)) / 4 * 3)
|
||||
|
||||
int
|
||||
base64_encode(const unsigned char *in, unsigned int inlen, char *out);
|
||||
|
||||
int
|
||||
base64_decode(const char *in, unsigned int inlen, unsigned char *out);
|
||||
|
||||
|
||||
#endif /* __BASE64_H__ */
|
308
shadowsocksr-libev/src/server/cache.c
Normal file
308
shadowsocksr-libev/src/server/cache.c
Normal file
@ -0,0 +1,308 @@
|
||||
/*
|
||||
* cache.c - Manage the connection cache for UDPRELAY
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* This file is part of the shadowsocks-libev.
|
||||
*
|
||||
* shadowsocks-libev is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* shadowsocks-libev is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with shadowsocks-libev; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Original Author: Oliver Lorenz (ol), olli@olorenz.org, https://olorenz.org
|
||||
* License: This is licensed under the same terms as uthash itself
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "cache.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include "win32.h"
|
||||
#endif
|
||||
|
||||
/** Creates a new cache object
|
||||
*
|
||||
* @param dst
|
||||
* Where the newly allocated cache object will be stored in
|
||||
*
|
||||
* @param capacity
|
||||
* The maximum number of elements this cache object can hold
|
||||
*
|
||||
* @return EINVAL if dst is NULL, ENOMEM if malloc fails, 0 otherwise
|
||||
*/
|
||||
int
|
||||
cache_create(struct cache **dst, const size_t capacity,
|
||||
void (*free_cb)(void *key, void *element))
|
||||
{
|
||||
struct cache *new = NULL;
|
||||
|
||||
if (!dst) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if ((new = malloc(sizeof(*new))) == NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
new->max_entries = capacity;
|
||||
new->entries = NULL;
|
||||
new->free_cb = free_cb;
|
||||
*dst = new;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Frees an allocated cache object
|
||||
*
|
||||
* @param cache
|
||||
* The cache object to free
|
||||
*
|
||||
* @param keep_data
|
||||
* Whether to free contained data or just delete references to it
|
||||
*
|
||||
* @return EINVAL if cache is NULL, 0 otherwise
|
||||
*/
|
||||
int
|
||||
cache_delete(struct cache *cache, int keep_data)
|
||||
{
|
||||
struct cache_entry *entry, *tmp;
|
||||
|
||||
if (!cache) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (keep_data) {
|
||||
HASH_CLEAR(hh, cache->entries);
|
||||
} else {
|
||||
HASH_ITER(hh, cache->entries, entry, tmp){
|
||||
HASH_DEL(cache->entries, entry);
|
||||
if (entry->data != NULL) {
|
||||
if (cache->free_cb) {
|
||||
cache->free_cb(entry->key, entry->data);
|
||||
} else {
|
||||
ss_free(entry->data);
|
||||
}
|
||||
}
|
||||
ss_free(entry->key);
|
||||
ss_free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
ss_free(cache);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Clear old cache object
|
||||
*
|
||||
* @param cache
|
||||
* The cache object to clear
|
||||
*
|
||||
* @param age
|
||||
* Clear only objects older than the age (sec)
|
||||
*
|
||||
* @return EINVAL if cache is NULL, 0 otherwise
|
||||
*/
|
||||
int
|
||||
cache_clear(struct cache *cache, ev_tstamp age)
|
||||
{
|
||||
struct cache_entry *entry, *tmp;
|
||||
|
||||
if (!cache) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
ev_tstamp now = ev_time();
|
||||
|
||||
HASH_ITER(hh, cache->entries, entry, tmp){
|
||||
if (now - entry->ts > age) {
|
||||
HASH_DEL(cache->entries, entry);
|
||||
if (entry->data != NULL) {
|
||||
if (cache->free_cb) {
|
||||
cache->free_cb(entry->key, entry->data);
|
||||
} else {
|
||||
ss_free(entry->data);
|
||||
}
|
||||
}
|
||||
ss_free(entry->key);
|
||||
ss_free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Removes a cache entry
|
||||
*
|
||||
* @param cache
|
||||
* The cache object
|
||||
*
|
||||
* @param key
|
||||
* The key of the entry to remove
|
||||
*
|
||||
* @param key_len
|
||||
* The length of key
|
||||
*
|
||||
* @return EINVAL if cache is NULL, 0 otherwise
|
||||
*/
|
||||
int
|
||||
cache_remove(struct cache *cache, char *key, size_t key_len)
|
||||
{
|
||||
struct cache_entry *tmp;
|
||||
|
||||
if (!cache || !key) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
HASH_FIND(hh, cache->entries, key, key_len, tmp);
|
||||
|
||||
if (tmp) {
|
||||
HASH_DEL(cache->entries, tmp);
|
||||
if (tmp->data != NULL) {
|
||||
if (cache->free_cb) {
|
||||
cache->free_cb(tmp->key, tmp->data);
|
||||
} else {
|
||||
ss_free(tmp->data);
|
||||
}
|
||||
}
|
||||
ss_free(tmp->key);
|
||||
ss_free(tmp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Checks if a given key is in the cache
|
||||
*
|
||||
* @param cache
|
||||
* The cache object
|
||||
*
|
||||
* @param key
|
||||
* The key to look-up
|
||||
*
|
||||
* @param key_len
|
||||
* The length of key
|
||||
*
|
||||
* @param result
|
||||
* Where to store the result if key is found.
|
||||
*
|
||||
* A warning: Even though result is just a pointer,
|
||||
* you have to call this function with a **ptr,
|
||||
* otherwise this will blow up in your face.
|
||||
*
|
||||
* @return EINVAL if cache is NULL, 0 otherwise
|
||||
*/
|
||||
int
|
||||
cache_lookup(struct cache *cache, char *key, size_t key_len, void *result)
|
||||
{
|
||||
struct cache_entry *tmp = NULL;
|
||||
char **dirty_hack = result;
|
||||
|
||||
if (!cache || !key || !result) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
HASH_FIND(hh, cache->entries, key, key_len, tmp);
|
||||
if (tmp) {
|
||||
HASH_DELETE(hh, cache->entries, tmp);
|
||||
tmp->ts = ev_time();
|
||||
HASH_ADD_KEYPTR(hh, cache->entries, tmp->key, key_len, tmp);
|
||||
*dirty_hack = tmp->data;
|
||||
} else {
|
||||
*dirty_hack = result = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cache_key_exist(struct cache *cache, char *key, size_t key_len)
|
||||
{
|
||||
struct cache_entry *tmp = NULL;
|
||||
|
||||
if (!cache || !key) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
HASH_FIND(hh, cache->entries, key, key_len, tmp);
|
||||
if (tmp) {
|
||||
HASH_DELETE(hh, cache->entries, tmp);
|
||||
tmp->ts = ev_time();
|
||||
HASH_ADD_KEYPTR(hh, cache->entries, tmp->key, key_len, tmp);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Inserts a given <key, value> pair into the cache
|
||||
*
|
||||
* @param cache
|
||||
* The cache object
|
||||
*
|
||||
* @param key
|
||||
* The key that identifies <value>
|
||||
*
|
||||
* @param key_len
|
||||
* The length of key
|
||||
*
|
||||
* @param data
|
||||
* Data associated with <key>
|
||||
*
|
||||
* @return EINVAL if cache is NULL, ENOMEM if malloc fails, 0 otherwise
|
||||
*/
|
||||
int
|
||||
cache_insert(struct cache *cache, char *key, size_t key_len, void *data)
|
||||
{
|
||||
struct cache_entry *entry = NULL;
|
||||
struct cache_entry *tmp_entry = NULL;
|
||||
|
||||
if (!cache) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if ((entry = malloc(sizeof(*entry))) == NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
entry->key = ss_malloc(key_len + 1);
|
||||
memcpy(entry->key, key, key_len);
|
||||
entry->key[key_len] = 0;
|
||||
|
||||
entry->data = data;
|
||||
entry->ts = ev_time();
|
||||
HASH_ADD_KEYPTR(hh, cache->entries, entry->key, key_len, entry);
|
||||
|
||||
if (HASH_COUNT(cache->entries) >= cache->max_entries) {
|
||||
HASH_ITER(hh, cache->entries, entry, tmp_entry){
|
||||
HASH_DELETE(hh, cache->entries, entry);
|
||||
if (entry->data != NULL) {
|
||||
if (cache->free_cb) {
|
||||
cache->free_cb(entry->key, entry->data);
|
||||
} else {
|
||||
ss_free(entry->data);
|
||||
}
|
||||
}
|
||||
ss_free(entry->key);
|
||||
ss_free(entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
62
shadowsocksr-libev/src/server/cache.h
Normal file
62
shadowsocksr-libev/src/server/cache.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* cache.h - Define the cache manager interface
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* This file is part of the shadowsocks-libev.
|
||||
*
|
||||
* shadowsocks-libev is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* shadowsocks-libev is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with shadowsocks-libev; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Original Author: Oliver Lorenz (ol), olli@olorenz.org, https://olorenz.org
|
||||
* License: This is licensed under the same terms as uthash itself
|
||||
*/
|
||||
|
||||
#ifndef _CACHE_
|
||||
#define _CACHE_
|
||||
|
||||
#include "uthash.h"
|
||||
#include "ev.h"
|
||||
|
||||
/**
|
||||
* A cache entry
|
||||
*/
|
||||
struct cache_entry {
|
||||
char *key; /**<The key */
|
||||
void *data; /**<Payload */
|
||||
ev_tstamp ts; /**<Timestamp */
|
||||
UT_hash_handle hh; /**<Hash Handle for uthash */
|
||||
};
|
||||
|
||||
/**
|
||||
* A cache object
|
||||
*/
|
||||
struct cache {
|
||||
size_t max_entries; /**<Amount of entries this cache object can hold */
|
||||
struct cache_entry *entries; /**<Head pointer for uthash */
|
||||
void (*free_cb) (void *key, void *element); /**<Callback function to free cache entries */
|
||||
};
|
||||
|
||||
int cache_create(struct cache **dst, const size_t capacity,
|
||||
void (*free_cb)(void *key, void *element));
|
||||
int cache_delete(struct cache *cache, int keep_data);
|
||||
int cache_clear(struct cache *cache, ev_tstamp age);
|
||||
int cache_lookup(struct cache *cache, char *key, size_t key_len, void *result);
|
||||
int cache_insert(struct cache *cache, char *key, size_t key_len, void *data);
|
||||
int cache_remove(struct cache *cache, char *key, size_t key_len);
|
||||
int cache_key_exist(struct cache *cache, char *key, size_t key_len);
|
||||
|
||||
#endif
|
236
shadowsocksr-libev/src/server/check.c
Normal file
236
shadowsocksr-libev/src/server/check.c
Normal file
@ -0,0 +1,236 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include<arpa/inet.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
|
||||
//#define __DEBUG__
|
||||
#ifdef __DEBUG__
|
||||
#define DEBUG(format,...) printf("File: "__FILE__", Line: %05d: "format"/n", __LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG(format,...)
|
||||
#endif
|
||||
|
||||
static sigjmp_buf jmpbuf;
|
||||
static void alarm_func()
|
||||
{
|
||||
siglongjmp(jmpbuf, 1);
|
||||
}
|
||||
|
||||
static struct hostent *timeGethostbyname(const char *domain, int timeout)
|
||||
{
|
||||
struct hostent *ipHostent = NULL;
|
||||
signal(SIGALRM, alarm_func);
|
||||
if(sigsetjmp(jmpbuf, 1) != 0)
|
||||
{
|
||||
alarm(0);//timout
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
return NULL;
|
||||
}
|
||||
alarm(timeout);//setting alarm
|
||||
ipHostent = gethostbyname(domain);
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
return ipHostent;
|
||||
}
|
||||
|
||||
|
||||
#define MY_HTTP_DEFAULT_PORT 80
|
||||
#define BUFFER_SIZE 1024
|
||||
#define HTTP_POST "POST /%s HTTP/1.1\r\nHOST: %s:%d\r\nAccept: */*\r\n"\
|
||||
"Content-Type:application/x-www-form-urlencoded\r\nContent-Length: %d\r\n\r\n%s"
|
||||
#define HTTP_GET "GET /%s HTTP/1.1\r\nHOST: %s:%d\r\nAccept: */*\r\n\r\n"
|
||||
|
||||
static int http_parse_url(const char *url,char *host,char *file,int *port)
|
||||
{
|
||||
char *ptr1,*ptr2;
|
||||
int len = 0;
|
||||
if(!url || !host || !file || !port){
|
||||
return 1;
|
||||
}
|
||||
|
||||
ptr1 = (char *)url;
|
||||
|
||||
if(!strncmp(ptr1,"http://",strlen("http://"))){
|
||||
ptr1 += strlen("http://");
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ptr2 = strchr(ptr1,'/');
|
||||
if(ptr2){
|
||||
len = strlen(ptr1) - strlen(ptr2);
|
||||
memcpy(host,ptr1,len);
|
||||
host[len] = '\0';
|
||||
if(*(ptr2 + 1)){
|
||||
memcpy(file,ptr2 + 1,strlen(ptr2) - 1 );
|
||||
file[strlen(ptr2) - 1] = '\0';
|
||||
}
|
||||
}else{
|
||||
memcpy(host,ptr1,strlen(ptr1));
|
||||
host[strlen(ptr1)] = '\0';
|
||||
}
|
||||
//get host and ip
|
||||
ptr1 = strchr(host,':');
|
||||
if(ptr1){
|
||||
*ptr1++ = '\0';
|
||||
*port = atoi(ptr1);
|
||||
}else{
|
||||
*port = MY_HTTP_DEFAULT_PORT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int http_tcpclient_recv(int socket,char *lpbuff){
|
||||
int recvnum = 0;
|
||||
|
||||
recvnum = recv(socket, lpbuff,BUFFER_SIZE*4,0);
|
||||
|
||||
return recvnum;
|
||||
}
|
||||
|
||||
static int http_tcpclient_send(int socket,char *buff,int size){
|
||||
int sent=0,tmpres=0;
|
||||
|
||||
while(sent < size){
|
||||
tmpres = send(socket,buff+sent,size-sent,0);
|
||||
if(tmpres == -1){
|
||||
return 1;
|
||||
}
|
||||
sent += tmpres;
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int http_get(const char *url,int socket_fd)
|
||||
{
|
||||
char lpbuf[BUFFER_SIZE*4] = {'\0'};
|
||||
|
||||
char host_addr[BUFFER_SIZE] = {'\0'};
|
||||
char file[BUFFER_SIZE] = {'\0'};
|
||||
int port = 0;
|
||||
|
||||
|
||||
if(!url){
|
||||
DEBUG(" failed!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(http_parse_url(url,host_addr,file,&port)){
|
||||
DEBUG("http_parse_url failed!\n");
|
||||
return 1;
|
||||
}
|
||||
DEBUG("url: %s\thost_addr : %s\tfile:%s\t,%d\n",url,host_addr,file,port);
|
||||
|
||||
|
||||
if(socket_fd < 0){
|
||||
DEBUG("http_tcpclient_create failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sprintf(lpbuf,HTTP_GET,file,host_addr,port);
|
||||
|
||||
if(http_tcpclient_send(socket_fd,lpbuf,strlen(lpbuf)) < 0){
|
||||
DEBUG("http_tcpclient_send failed..\n");
|
||||
return 1;
|
||||
}
|
||||
DEBUG("request:\n%s\n",lpbuf);
|
||||
|
||||
if(http_tcpclient_recv(socket_fd,lpbuf) <= 0){
|
||||
DEBUG("http_tcpclient_recv failed\n");
|
||||
close(socket_fd);
|
||||
return 1;
|
||||
}
|
||||
DEBUG("rec:\n%s\n",lpbuf);
|
||||
close(socket_fd);
|
||||
|
||||
//return http_parse_result(lpbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int fd,http_flag=0,http_ret=1;
|
||||
struct sockaddr_in addr;
|
||||
struct hostent *host;
|
||||
struct timeval timeo = {3, 0};
|
||||
socklen_t len = sizeof(timeo);
|
||||
|
||||
char http_url[100]="http://";
|
||||
|
||||
|
||||
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (argc >= 4)
|
||||
timeo.tv_sec = atoi(argv[3]);
|
||||
if (argc>=5)
|
||||
http_flag=1;
|
||||
|
||||
if((host=timeGethostbyname(argv[1],timeo.tv_sec)) == NULL) {
|
||||
DEBUG("gethostbyname err\n");
|
||||
return 1;
|
||||
}
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeo, len) == -1)
|
||||
{
|
||||
|
||||
DEBUG("setsockopt send err\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeo, len) == -1)
|
||||
{
|
||||
|
||||
DEBUG("setsockopt recv err\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr = *((struct in_addr *)host->h_addr);
|
||||
//addr.sin_addr.s_addr = inet_addr(argv[1]);
|
||||
addr.sin_port = htons(atoi(argv[2]));
|
||||
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
|
||||
{
|
||||
if (errno == EINPROGRESS)
|
||||
{
|
||||
DEBUG("timeout err\n");
|
||||
return 1;
|
||||
}
|
||||
DEBUG("connect err\n");
|
||||
return 1;
|
||||
}
|
||||
if(http_flag==0)
|
||||
{
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
strcat(http_url,argv[1]);
|
||||
http_ret=http_get(http_url,fd);
|
||||
if(http_ret==1)
|
||||
{
|
||||
DEBUG("recv err");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG("recv ok");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
58
shadowsocksr-libev/src/server/common.h
Normal file
58
shadowsocksr-libev/src/server/common.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* common.h - Provide global definitions
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* This file is part of the shadowsocks-libev.
|
||||
* shadowsocks-libev is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* shadowsocks-libev is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with shadowsocks-libev; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _COMMON_H
|
||||
#define _COMMON_H
|
||||
|
||||
#define DEFAULT_CONF_PATH "/etc/shadowsocks-libev/config.json"
|
||||
|
||||
#ifndef SOL_TCP
|
||||
#define SOL_TCP IPPROTO_TCP
|
||||
#endif
|
||||
|
||||
#if defined(MODULE_TUNNEL) || defined(MODULE_REDIR)
|
||||
#define MODULE_LOCAL
|
||||
#endif
|
||||
|
||||
int init_udprelay(const char *server_host, const char *server_port,
|
||||
#ifdef MODULE_LOCAL
|
||||
const struct sockaddr *remote_addr, const int remote_addr_len,
|
||||
#ifdef MODULE_TUNNEL
|
||||
const ss_addr_t tunnel_addr,
|
||||
#endif
|
||||
#endif
|
||||
int mtu, int method, int auth, int timeout, const char *iface, const char *protocol, const char *protocol_param);
|
||||
|
||||
void free_udprelay(void);
|
||||
|
||||
#ifdef ANDROID
|
||||
int protect_socket(int fd);
|
||||
int send_traffic_stat(uint64_t tx, uint64_t rx);
|
||||
#endif
|
||||
|
||||
#define STAGE_ERROR -1 /* Error detected */
|
||||
#define STAGE_INIT 0 /* Initial stage */
|
||||
#define STAGE_HANDSHAKE 1 /* Handshake with client */
|
||||
#define STAGE_PARSE 2 /* Parse the header */
|
||||
#define STAGE_RESOLVE 4 /* Resolve the hostname */
|
||||
#define STAGE_STREAM 5 /* Stream between client and server */
|
||||
|
||||
#endif // _COMMON_H
|
97
shadowsocksr-libev/src/server/crc32.c
Normal file
97
shadowsocksr-libev/src/server/crc32.c
Normal file
@ -0,0 +1,97 @@
|
||||
static uint32_t crc32_table[256] = {0};
|
||||
|
||||
void init_crc32_table(void) {
|
||||
uint32_t c, i, j;
|
||||
if (crc32_table[0] == 0) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
c = i;
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (c & 1)
|
||||
c = 0xedb88320L ^ (c >> 1);
|
||||
else
|
||||
c = c >> 1;
|
||||
}
|
||||
crc32_table[i] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t crc32(unsigned char *buffer, unsigned int size) {
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
unsigned int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
crc = crc32_table[(crc ^ buffer[i]) & 0xFF] ^ (crc >> 8);
|
||||
}
|
||||
return crc ^ 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
void fillcrc32to(unsigned char *buffer, unsigned int size, unsigned char *outbuffer) {
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
unsigned int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
crc = crc32_table[(crc ^ buffer[i]) & 0xff] ^ (crc >> 8);
|
||||
}
|
||||
crc ^= 0xFFFFFFFF;
|
||||
outbuffer[0] = crc;
|
||||
outbuffer[1] = crc >> 8;
|
||||
outbuffer[2] = crc >> 16;
|
||||
outbuffer[3] = crc >> 24;
|
||||
}
|
||||
|
||||
void fillcrc32(unsigned char *buffer, unsigned int size) {
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
unsigned int i;
|
||||
size -= 4;
|
||||
for (i = 0; i < size; i++) {
|
||||
crc = crc32_table[(crc ^ buffer[i]) & 0xff] ^ (crc >> 8);
|
||||
}
|
||||
buffer += size;
|
||||
buffer[0] = crc;
|
||||
buffer[1] = crc >> 8;
|
||||
buffer[2] = crc >> 16;
|
||||
buffer[3] = crc >> 24;
|
||||
}
|
||||
|
||||
void adler32_short(unsigned char *buffer, unsigned int size, uint32_t *a, uint32_t *b) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
*a += buffer[i];
|
||||
*b += *a;
|
||||
}
|
||||
*a %= 65521;
|
||||
*b %= 65521;
|
||||
}
|
||||
|
||||
#define NMAX 5552
|
||||
uint32_t adler32(unsigned char *buffer, unsigned int size) {
|
||||
uint32_t a = 1;
|
||||
uint32_t b = 0;
|
||||
while ( size >= NMAX ) {
|
||||
adler32_short(buffer, NMAX, &a, &b);
|
||||
buffer += NMAX;
|
||||
size -= NMAX;
|
||||
}
|
||||
adler32_short(buffer, size, &a, &b);
|
||||
return (b << 16) + a;
|
||||
}
|
||||
#undef NMAX
|
||||
|
||||
void filladler32(unsigned char *buffer, unsigned int size) {
|
||||
size -= 4;
|
||||
uint32_t checksum = adler32(buffer, size);
|
||||
buffer += size;
|
||||
buffer[0] = checksum;
|
||||
buffer[1] = checksum >> 8;
|
||||
buffer[2] = checksum >> 16;
|
||||
buffer[3] = checksum >> 24;
|
||||
}
|
||||
|
||||
int checkadler32(unsigned char *buffer, unsigned int size) {
|
||||
size -= 4;
|
||||
uint32_t checksum = adler32(buffer, size);
|
||||
buffer += size;
|
||||
return checksum == (((uint32_t)buffer[3] << 24)
|
||||
| ((uint32_t)buffer[2] << 16)
|
||||
| ((uint32_t)buffer[1] << 8)
|
||||
| (uint32_t)buffer[0]);
|
||||
}
|
||||
|
1645
shadowsocksr-libev/src/server/encrypt.c
Normal file
1645
shadowsocksr-libev/src/server/encrypt.c
Normal file
File diff suppressed because it is too large
Load Diff
222
shadowsocksr-libev/src/server/encrypt.h
Normal file
222
shadowsocksr-libev/src/server/encrypt.h
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* encrypt.h - Define the enryptor's interface
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* This file is part of the shadowsocks-libev.
|
||||
*
|
||||
* shadowsocks-libev is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* shadowsocks-libev is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with shadowsocks-libev; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ENCRYPT_H
|
||||
#define _ENCRYPT_H
|
||||
|
||||
#ifndef __MINGW32__
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/md5.h>
|
||||
typedef EVP_CIPHER cipher_kt_t;
|
||||
typedef EVP_CIPHER_CTX cipher_evp_t;
|
||||
typedef EVP_MD digest_type_t;
|
||||
#define MAX_KEY_LENGTH EVP_MAX_KEY_LENGTH
|
||||
#define MAX_IV_LENGTH EVP_MAX_IV_LENGTH
|
||||
#define MAX_MD_SIZE EVP_MAX_MD_SIZE
|
||||
|
||||
#elif defined(USE_CRYPTO_POLARSSL)
|
||||
|
||||
#include <polarssl/cipher.h>
|
||||
#include <polarssl/md.h>
|
||||
typedef cipher_info_t cipher_kt_t;
|
||||
typedef cipher_context_t cipher_evp_t;
|
||||
typedef md_info_t digest_type_t;
|
||||
#define MAX_KEY_LENGTH 64
|
||||
#define MAX_IV_LENGTH POLARSSL_MAX_IV_LENGTH
|
||||
#define MAX_MD_SIZE POLARSSL_MD_MAX_SIZE
|
||||
|
||||
#elif defined(USE_CRYPTO_MBEDTLS)
|
||||
|
||||
#include <mbedtls/cipher.h>
|
||||
#include <mbedtls/md.h>
|
||||
typedef mbedtls_cipher_info_t cipher_kt_t;
|
||||
typedef mbedtls_cipher_context_t cipher_evp_t;
|
||||
typedef mbedtls_md_info_t digest_type_t;
|
||||
#define MAX_KEY_LENGTH 64
|
||||
#define MAX_IV_LENGTH MBEDTLS_MAX_IV_LENGTH
|
||||
#define MAX_MD_SIZE MBEDTLS_MD_MAX_SIZE
|
||||
|
||||
/* we must have MBEDTLS_CIPHER_MODE_CFB defined */
|
||||
#if !defined(MBEDTLS_CIPHER_MODE_CFB)
|
||||
#error Cipher Feedback mode a.k.a CFB not supported by your mbed TLS.
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_CRYPTO_APPLECC
|
||||
|
||||
#include <CommonCrypto/CommonCrypto.h>
|
||||
|
||||
#define kCCAlgorithmInvalid UINT32_MAX
|
||||
#define kCCContextValid 0
|
||||
#define kCCContextInvalid -1
|
||||
|
||||
typedef struct {
|
||||
CCCryptorRef cryptor;
|
||||
int valid;
|
||||
CCOperation encrypt;
|
||||
CCAlgorithm cipher;
|
||||
CCMode mode;
|
||||
CCPadding padding;
|
||||
uint8_t iv[MAX_IV_LENGTH];
|
||||
uint8_t key[MAX_KEY_LENGTH];
|
||||
size_t iv_len;
|
||||
size_t key_len;
|
||||
} cipher_cc_t;
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
cipher_evp_t *evp;
|
||||
#ifdef USE_CRYPTO_APPLECC
|
||||
cipher_cc_t cc;
|
||||
#endif
|
||||
uint8_t iv[MAX_IV_LENGTH];
|
||||
} cipher_ctx_t;
|
||||
|
||||
typedef struct {
|
||||
cipher_kt_t *info;
|
||||
size_t iv_len;
|
||||
size_t key_len;
|
||||
} cipher_t;
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#elif HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#define SODIUM_BLOCK_SIZE 64
|
||||
|
||||
enum crpher_index {
|
||||
NONE = -1,
|
||||
TABLE = 0,
|
||||
RC4,
|
||||
RC4_MD5_6,
|
||||
RC4_MD5,
|
||||
AES_128_CFB,
|
||||
AES_192_CFB,
|
||||
AES_256_CFB,
|
||||
AES_128_CTR,
|
||||
AES_192_CTR,
|
||||
AES_256_CTR,
|
||||
BF_CFB,
|
||||
CAMELLIA_128_CFB,
|
||||
CAMELLIA_192_CFB,
|
||||
CAMELLIA_256_CFB,
|
||||
CAST5_CFB,
|
||||
DES_CFB,
|
||||
IDEA_CFB,
|
||||
RC2_CFB,
|
||||
SEED_CFB,
|
||||
SALSA20,
|
||||
CHACHA20,
|
||||
CHACHA20IETF,
|
||||
CIPHER_NUM,
|
||||
};
|
||||
|
||||
#define ONETIMEAUTH_FLAG 0x10
|
||||
#define ADDRTYPE_MASK 0xEF
|
||||
|
||||
#define ONETIMEAUTH_BYTES 10U
|
||||
#define MD5_BYTES 16U
|
||||
#define SHA1_BYTES 20U
|
||||
#define CLEN_BYTES 2U
|
||||
#define AUTH_BYTES (ONETIMEAUTH_BYTES + CLEN_BYTES)
|
||||
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
typedef struct buffer {
|
||||
size_t idx;
|
||||
size_t len;
|
||||
size_t capacity;
|
||||
char *array;
|
||||
} buffer_t;
|
||||
|
||||
typedef struct chunk {
|
||||
uint32_t idx;
|
||||
uint32_t len;
|
||||
uint32_t counter;
|
||||
buffer_t *buf;
|
||||
} chunk_t;
|
||||
|
||||
typedef struct enc_ctx {
|
||||
uint8_t init;
|
||||
uint64_t counter;
|
||||
cipher_ctx_t evp;
|
||||
} enc_ctx_t;
|
||||
|
||||
void bytes_to_key_with_size(const char *pass, size_t len, uint8_t *md, size_t md_size);
|
||||
|
||||
int ss_encrypt_all(buffer_t *plaintext, int method, int auth, size_t capacity);
|
||||
int ss_decrypt_all(buffer_t *ciphertext, int method, int auth, size_t capacity);
|
||||
int ss_encrypt(buffer_t *plaintext, enc_ctx_t *ctx, size_t capacity);
|
||||
int ss_decrypt(buffer_t *ciphertext, enc_ctx_t *ctx, size_t capacity);
|
||||
|
||||
void enc_ctx_init(int method, enc_ctx_t *ctx, int enc);
|
||||
int enc_init(const char *pass, const char *method);
|
||||
int enc_get_iv_len(void);
|
||||
uint8_t* enc_get_key(void);
|
||||
int enc_get_key_len(void);
|
||||
void cipher_context_release(cipher_ctx_t *evp);
|
||||
unsigned char *enc_md5(const unsigned char *d, size_t n, unsigned char *md);
|
||||
|
||||
int ss_md5_hmac(char *auth, char *msg, int msg_len, uint8_t *iv);
|
||||
int ss_md5_hmac_with_key(char *auth, char *msg, int msg_len, uint8_t *auth_key, int key_len);
|
||||
int ss_md5_hash_func(char *auth, char *msg, int msg_len);
|
||||
int ss_sha1_hmac(char *auth, char *msg, int msg_len, uint8_t *iv);
|
||||
int ss_sha1_hmac_with_key(char *auth, char *msg, int msg_len, uint8_t *auth_key, int key_len);
|
||||
int ss_sha1_hash_func(char *auth, char *msg, int msg_len);
|
||||
int ss_aes_128_cbc(char *encrypt, char *out_data, char *key);
|
||||
int ss_onetimeauth(buffer_t *buf, uint8_t *iv, size_t capacity);
|
||||
int ss_onetimeauth_verify(buffer_t *buf, uint8_t *iv);
|
||||
|
||||
int ss_check_hash(buffer_t *buf, chunk_t *chunk, enc_ctx_t *ctx, size_t capacity);
|
||||
int ss_gen_hash(buffer_t *buf, uint32_t *counter, enc_ctx_t *ctx, size_t capacity);
|
||||
|
||||
int balloc(buffer_t *ptr, size_t capacity);
|
||||
int brealloc(buffer_t *ptr, size_t len, size_t capacity);
|
||||
void bfree(buffer_t *ptr);
|
||||
|
||||
#endif // _ENCRYPT_H
|
152
shadowsocksr-libev/src/server/http.c
Normal file
152
shadowsocksr-libev/src/server/http.c
Normal file
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* malloc() */
|
||||
#include <string.h> /* strncpy() */
|
||||
#include <strings.h> /* strncasecmp() */
|
||||
#include <ctype.h> /* isblank() */
|
||||
|
||||
#include "http.h"
|
||||
#include "protocol.h"
|
||||
|
||||
#define SERVER_NAME_LEN 256
|
||||
|
||||
static int parse_http_header(const char *, size_t, char **);
|
||||
static int get_header(const char *, const char *, int, char **);
|
||||
static int next_header(const char **, int *);
|
||||
|
||||
static const protocol_t http_protocol_st = {
|
||||
.default_port = 80,
|
||||
.parse_packet = &parse_http_header,
|
||||
};
|
||||
const protocol_t *const http_protocol = &http_protocol_st;
|
||||
|
||||
/*
|
||||
* Parses a HTTP request for the Host: header
|
||||
*
|
||||
* Returns:
|
||||
* >=0 - length of the hostname and updates *hostname
|
||||
* caller is responsible for freeing *hostname
|
||||
* -1 - Incomplete request
|
||||
* -2 - No Host header included in this request
|
||||
* -3 - Invalid hostname pointer
|
||||
* -4 - malloc failure
|
||||
* < -4 - Invalid HTTP request
|
||||
*
|
||||
*/
|
||||
static int
|
||||
parse_http_header(const char *data, size_t data_len, char **hostname)
|
||||
{
|
||||
int result, i;
|
||||
|
||||
if (hostname == NULL)
|
||||
return -3;
|
||||
|
||||
if (data_len == 0)
|
||||
return -1;
|
||||
|
||||
result = get_header("Host:", data, data_len, hostname);
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
/*
|
||||
* if the user specifies the port in the request, it is included here.
|
||||
* Host: example.com:80
|
||||
* so we trim off port portion
|
||||
*/
|
||||
for (i = result - 1; i >= 0; i--)
|
||||
if ((*hostname)[i] == ':') {
|
||||
(*hostname)[i] = '\0';
|
||||
result = i;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
get_header(const char *header, const char *data, int data_len, char **value)
|
||||
{
|
||||
int len, header_len;
|
||||
|
||||
header_len = strlen(header);
|
||||
|
||||
/* loop through headers stopping at first blank line */
|
||||
while ((len = next_header(&data, &data_len)) != 0)
|
||||
if (len > header_len && strncasecmp(header, data, header_len) == 0) {
|
||||
/* Eat leading whitespace */
|
||||
while (header_len < len && isblank(data[header_len]))
|
||||
header_len++;
|
||||
|
||||
*value = malloc(len - header_len + 1);
|
||||
if (*value == NULL)
|
||||
return -4;
|
||||
|
||||
strncpy(*value, data + header_len, len - header_len);
|
||||
(*value)[len - header_len] = '\0';
|
||||
|
||||
return len - header_len;
|
||||
}
|
||||
|
||||
/* If there is no data left after reading all the headers then we do not
|
||||
* have a complete HTTP request, there must be a blank line */
|
||||
if (data_len == 0)
|
||||
return -1;
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int
|
||||
next_header(const char **data, int *len)
|
||||
{
|
||||
int header_len;
|
||||
|
||||
/* perhaps we can optimize this to reuse the value of header_len, rather
|
||||
* than scanning twice.
|
||||
* Walk our data stream until the end of the header */
|
||||
while (*len > 2 && (*data)[0] != '\r' && (*data)[1] != '\n') {
|
||||
(*len)--;
|
||||
(*data)++;
|
||||
}
|
||||
|
||||
/* advanced past the <CR><LF> pair */
|
||||
*data += 2;
|
||||
*len -= 2;
|
||||
|
||||
/* Find the length of the next header */
|
||||
header_len = 0;
|
||||
while (*len > header_len + 1
|
||||
&& (*data)[header_len] != '\r'
|
||||
&& (*data)[header_len + 1] != '\n')
|
||||
header_len++;
|
||||
|
||||
return header_len;
|
||||
}
|
34
shadowsocksr-libev/src/server/http.h
Normal file
34
shadowsocksr-libev/src/server/http.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef HTTP_H
|
||||
#define HTTP_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "protocol.h"
|
||||
|
||||
const protocol_t *const http_protocol;
|
||||
|
||||
#endif
|
626
shadowsocksr-libev/src/server/http_simple.c
Normal file
626
shadowsocksr-libev/src/server/http_simple.c
Normal file
@ -0,0 +1,626 @@
|
||||
|
||||
#include "http_simple.h"
|
||||
|
||||
static char* g_useragent[] = {
|
||||
"Mozilla/5.0 (Windows NT 6.3; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0",
|
||||
"Mozilla/5.0 (Windows NT 6.3; WOW64; rv:40.0) Gecko/20100101 Firefox/44.0",
|
||||
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.11 (KHTML, like Gecko) Ubuntu/11.10 Chromium/27.0.1453.93 Chrome/27.0.1453.93 Safari/537.36",
|
||||
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:35.0) Gecko/20100101 Firefox/35.0",
|
||||
"Mozilla/5.0 (compatible; WOW64; MSIE 10.0; Windows NT 6.2)",
|
||||
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27",
|
||||
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C)",
|
||||
"Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko",
|
||||
"Mozilla/5.0 (Linux; Android 4.4; Nexus 5 Build/BuildID) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36",
|
||||
"Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3",
|
||||
"Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3",
|
||||
};
|
||||
|
||||
static int g_useragent_index = -1;
|
||||
|
||||
typedef struct http_simple_local_data {
|
||||
int has_sent_header;
|
||||
int has_recv_header;
|
||||
char *encode_buffer;
|
||||
int host_matched;
|
||||
char *recv_buffer;
|
||||
int recv_buffer_size;
|
||||
}http_simple_local_data;
|
||||
|
||||
void http_simple_local_data_init(http_simple_local_data* local) {
|
||||
local->has_sent_header = 0;
|
||||
local->has_recv_header = 0;
|
||||
local->encode_buffer = NULL;
|
||||
|
||||
local->recv_buffer = malloc(0);
|
||||
local->recv_buffer_size = 0;
|
||||
|
||||
local->host_matched = 0;
|
||||
|
||||
if (g_useragent_index == -1) {
|
||||
g_useragent_index = xorshift128plus() % (sizeof(g_useragent) / sizeof(*g_useragent));
|
||||
}
|
||||
}
|
||||
|
||||
obfs * http_simple_new_obfs() {
|
||||
obfs * self = new_obfs();
|
||||
self->l_data = malloc(sizeof(http_simple_local_data));
|
||||
http_simple_local_data_init((http_simple_local_data*)self->l_data);
|
||||
return self;
|
||||
}
|
||||
|
||||
void http_simple_dispose(obfs *self) {
|
||||
http_simple_local_data *local = (http_simple_local_data*)self->l_data;
|
||||
if (local->encode_buffer != NULL) {
|
||||
free(local->encode_buffer);
|
||||
local->encode_buffer = NULL;
|
||||
}
|
||||
free(local);
|
||||
dispose_obfs(self);
|
||||
}
|
||||
|
||||
char http_simple_hex(char c) {
|
||||
if (c < 10) return c + '0';
|
||||
return c - 10 + 'a';
|
||||
}
|
||||
|
||||
int get_data_from_http_header(char *data, char **outdata) {
|
||||
char *delim = "\r\n";
|
||||
char *delim_hex = "%";
|
||||
int outlength = 0;
|
||||
|
||||
char *buf = *outdata;
|
||||
char *p_line;
|
||||
p_line = strtok(data, delim);
|
||||
|
||||
//while(p_line)
|
||||
{
|
||||
char *p_hex;
|
||||
|
||||
p_hex = strtok(p_line, delim_hex);
|
||||
|
||||
while((p_hex = strtok(NULL, delim_hex)))
|
||||
{
|
||||
char hex = 0;
|
||||
|
||||
if(strlen(p_hex) <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(strlen(p_hex) > 2)
|
||||
{
|
||||
char *c_hex = (char*)malloc(2);
|
||||
memcpy(c_hex, p_hex, 2);
|
||||
hex = (char)strtol(c_hex, NULL, 16);
|
||||
free(c_hex);
|
||||
}
|
||||
else
|
||||
{
|
||||
hex = (char)strtol(p_hex, NULL, 16);
|
||||
}
|
||||
|
||||
outlength += 1;
|
||||
buf = (char*)realloc(buf, outlength);
|
||||
buf[outlength - 1] = hex;
|
||||
}
|
||||
|
||||
//p_line = strtok(p_line, delim);
|
||||
}
|
||||
*outdata = buf;
|
||||
return outlength;
|
||||
}
|
||||
|
||||
void get_host_from_http_header(char *data, char **host) {
|
||||
char* data_begin = strstr(data, "Host: ");
|
||||
|
||||
if(data_begin == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
data_begin += 6;
|
||||
char* data_end = strstr(data_begin, "\r\n");
|
||||
char* data_end_port = strstr(data_begin, ":");
|
||||
|
||||
int host_length = 0;
|
||||
|
||||
if(data_end_port != NULL)
|
||||
{
|
||||
host_length = data_end_port - data_begin;
|
||||
}
|
||||
else
|
||||
{
|
||||
host_length = data_end - data_begin;
|
||||
}
|
||||
|
||||
if(host_length <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
memset(*host, 0x00, 1024);
|
||||
memcpy(*host, data_begin, host_length);
|
||||
}
|
||||
|
||||
void http_simple_encode_head(http_simple_local_data *local, char *data, int datalength) {
|
||||
if (local->encode_buffer == NULL) {
|
||||
local->encode_buffer = (char*)malloc(datalength * 3 + 1);
|
||||
}
|
||||
int pos = 0;
|
||||
for (; pos < datalength; ++pos) {
|
||||
local->encode_buffer[pos * 3] = '%';
|
||||
local->encode_buffer[pos * 3 + 1] = http_simple_hex(((unsigned char)data[pos] >> 4));
|
||||
local->encode_buffer[pos * 3 + 2] = http_simple_hex(data[pos] & 0xF);
|
||||
}
|
||||
local->encode_buffer[pos * 3] = 0;
|
||||
}
|
||||
|
||||
int http_simple_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
http_simple_local_data *local = (http_simple_local_data*)self->l_data;
|
||||
if (local->has_sent_header) {
|
||||
return datalength;
|
||||
}
|
||||
char hosts[1024];
|
||||
char * phost[128];
|
||||
int host_num = 0;
|
||||
int pos;
|
||||
char hostport[128];
|
||||
int head_size = self->server.head_len + (xorshift128plus() & 0x3F);
|
||||
int outlength;
|
||||
char * out_buffer = (char*)malloc(datalength + 2048);
|
||||
char * body_buffer = NULL;
|
||||
if (head_size > datalength)
|
||||
head_size = datalength;
|
||||
http_simple_encode_head(local, encryptdata, head_size);
|
||||
if (self->server.param && strlen(self->server.param) == 0)
|
||||
self->server.param = NULL;
|
||||
strncpy(hosts, self->server.param ? self->server.param : self->server.host, sizeof hosts);
|
||||
phost[host_num++] = hosts;
|
||||
for (pos = 0; hosts[pos]; ++pos) {
|
||||
if (hosts[pos] == ',') {
|
||||
phost[host_num++] = &hosts[pos + 1];
|
||||
hosts[pos] = 0;
|
||||
} else if (hosts[pos] == '#') {
|
||||
char * body_pointer = &hosts[pos + 1];
|
||||
char * p;
|
||||
int trans_char = 0;
|
||||
p = body_buffer = (char*)malloc(2048);
|
||||
for ( ; *body_pointer; ++body_pointer) {
|
||||
if (*body_pointer == '\\') {
|
||||
trans_char = 1;
|
||||
continue;
|
||||
} else if (*body_pointer == '\n') {
|
||||
*p = '\r';
|
||||
*++p = '\n';
|
||||
continue;
|
||||
}
|
||||
if (trans_char) {
|
||||
if (*body_pointer == '\\' ) {
|
||||
*p = '\\';
|
||||
} else if (*body_pointer == 'n' ) {
|
||||
*p = '\r';
|
||||
*++p = '\n';
|
||||
} else {
|
||||
*p = '\\';
|
||||
*p = *body_pointer;
|
||||
}
|
||||
trans_char = 0;
|
||||
} else {
|
||||
*p = *body_pointer;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
*p = 0;
|
||||
hosts[pos] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
host_num = xorshift128plus() % host_num;
|
||||
if (self->server.port == 80)
|
||||
sprintf(hostport, "%s", phost[host_num]);
|
||||
else
|
||||
sprintf(hostport, "%s:%d", phost[host_num], self->server.port);
|
||||
if (body_buffer) {
|
||||
sprintf(out_buffer,
|
||||
"GET /%s HTTP/1.1\r\n"
|
||||
"Host: %s\r\n"
|
||||
"%s\r\n\r\n",
|
||||
local->encode_buffer,
|
||||
hostport,
|
||||
body_buffer);
|
||||
} else {
|
||||
sprintf(out_buffer,
|
||||
"GET /%s HTTP/1.1\r\n"
|
||||
"Host: %s\r\n"
|
||||
"User-Agent: %s\r\n"
|
||||
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
|
||||
"Accept-Language: en-US,en;q=0.8\r\n"
|
||||
"Accept-Encoding: gzip, deflate\r\n"
|
||||
"DNT: 1\r\n"
|
||||
"Connection: keep-alive\r\n"
|
||||
"\r\n",
|
||||
local->encode_buffer,
|
||||
hostport,
|
||||
g_useragent[g_useragent_index]
|
||||
);
|
||||
}
|
||||
//LOGI("http header: %s", out_buffer);
|
||||
outlength = strlen(out_buffer);
|
||||
memmove(out_buffer + outlength, encryptdata + head_size, datalength - head_size);
|
||||
outlength += datalength - head_size;
|
||||
local->has_sent_header = 1;
|
||||
if (*capacity < outlength) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memmove(encryptdata, out_buffer, outlength);
|
||||
free(out_buffer);
|
||||
if (body_buffer != NULL)
|
||||
free(body_buffer);
|
||||
if (local->encode_buffer != NULL) {
|
||||
free(local->encode_buffer);
|
||||
local->encode_buffer = NULL;
|
||||
}
|
||||
return outlength;
|
||||
}
|
||||
|
||||
int http_simple_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
http_simple_local_data *local = (http_simple_local_data*)self->l_data;
|
||||
if (local->has_sent_header) {
|
||||
return datalength;
|
||||
}
|
||||
int outlength;
|
||||
char * out_buffer = (char*)malloc(datalength + 2048);
|
||||
|
||||
time_t now;
|
||||
struct tm *tm_now;
|
||||
char datetime[200];
|
||||
|
||||
time(&now);
|
||||
tm_now = localtime(&now);
|
||||
strftime(datetime, 200, "%a, %d %b %Y %H:%M:%S GMT", tm_now);
|
||||
|
||||
sprintf(out_buffer,
|
||||
"HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nContent-Encoding: gzip\r\nContent-Type: text/html\r\nDate: "
|
||||
"%s"
|
||||
"\r\nServer: nginx\r\nVary: Accept-Encoding\r\n\r\n",
|
||||
datetime);
|
||||
|
||||
outlength = strlen(out_buffer);
|
||||
memmove(out_buffer + outlength, encryptdata, datalength);
|
||||
outlength += datalength;
|
||||
|
||||
local->has_sent_header = 1;
|
||||
if (*capacity < outlength) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memmove(encryptdata, out_buffer, outlength);
|
||||
free(out_buffer);
|
||||
return outlength;
|
||||
}
|
||||
|
||||
int http_simple_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
http_simple_local_data *local = (http_simple_local_data*)self->l_data;
|
||||
*needsendback = 0;
|
||||
if (local->has_recv_header) {
|
||||
return datalength;
|
||||
}
|
||||
char* data_begin = strstr(encryptdata, "\r\n\r\n");
|
||||
if (data_begin) {
|
||||
int outlength;
|
||||
data_begin += 4;
|
||||
local->has_recv_header = 1;
|
||||
outlength = datalength - (data_begin - encryptdata);
|
||||
memmove(encryptdata, data_begin, outlength);
|
||||
return outlength;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int http_simple_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
http_simple_local_data *local = (http_simple_local_data*)self->l_data;
|
||||
*needsendback = 0;
|
||||
if (local->has_recv_header) {
|
||||
return datalength;
|
||||
}
|
||||
|
||||
if(datalength != 0)
|
||||
{
|
||||
local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size + datalength);
|
||||
memmove(local->recv_buffer + local->recv_buffer_size, encryptdata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
|
||||
int outlength = local->recv_buffer_size;
|
||||
if (*capacity < outlength) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memcpy(encryptdata, local->recv_buffer, local->recv_buffer_size);
|
||||
}
|
||||
|
||||
if(local->recv_buffer_size > 10)
|
||||
{
|
||||
if(strstr(local->recv_buffer, "GET /") == local->recv_buffer || strstr(local->recv_buffer, "POST /") == local->recv_buffer)
|
||||
{
|
||||
if(local->recv_buffer_size > 65536)
|
||||
{
|
||||
free(local->recv_buffer);
|
||||
local->recv_buffer = malloc(0);
|
||||
local->recv_buffer_size = 0;
|
||||
local->has_sent_header = 1;
|
||||
local->has_recv_header = 1;
|
||||
LOGE("http_simple: over size");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
free(local->recv_buffer);
|
||||
local->recv_buffer = malloc(0);
|
||||
local->recv_buffer_size = 0;
|
||||
local->has_sent_header = 1;
|
||||
local->has_recv_header = 1;
|
||||
LOGE("http_simple: not match begin");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGE("http_simple: too short");
|
||||
local->has_sent_header = 1;
|
||||
local->has_recv_header = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char* data_begin = strstr(encryptdata, "\r\n\r\n");
|
||||
if (data_begin) {
|
||||
int outlength;
|
||||
char *ret_buf = (char*)malloc(*capacity);
|
||||
memset(ret_buf, 0x00, *capacity);
|
||||
int ret_buf_len = 0;
|
||||
ret_buf_len = get_data_from_http_header(encryptdata, &ret_buf);
|
||||
|
||||
if (self->server.param && strlen(self->server.param) == 0)
|
||||
{
|
||||
self->server.param = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(local->host_matched == 0)
|
||||
{
|
||||
char *host = (char*)malloc(1024);
|
||||
get_host_from_http_header(local->recv_buffer, &host);
|
||||
char hosts[1024];
|
||||
char * phost[128];
|
||||
int host_num = 0;
|
||||
int pos = 0;
|
||||
int is_match = 0;
|
||||
char * body_buffer = NULL;
|
||||
strncpy(hosts, self->server.param, sizeof hosts);
|
||||
phost[host_num++] = hosts;
|
||||
|
||||
for (pos = 0; hosts[pos]; ++pos) {
|
||||
if (hosts[pos] == ',') {
|
||||
phost[host_num++] = &hosts[pos + 1];
|
||||
hosts[pos] = 0;
|
||||
} else if (hosts[pos] == '#') {
|
||||
char * body_pointer = &hosts[pos + 1];
|
||||
char * p;
|
||||
int trans_char = 0;
|
||||
p = body_buffer = (char*)malloc(2048);
|
||||
for ( ; *body_pointer; ++body_pointer) {
|
||||
if (*body_pointer == '\\') {
|
||||
trans_char = 1;
|
||||
continue;
|
||||
} else if (*body_pointer == '\n') {
|
||||
*p = '\r';
|
||||
*++p = '\n';
|
||||
continue;
|
||||
}
|
||||
if (trans_char) {
|
||||
if (*body_pointer == '\\' ) {
|
||||
*p = '\\';
|
||||
} else if (*body_pointer == 'n' ) {
|
||||
*p = '\r';
|
||||
*++p = '\n';
|
||||
} else {
|
||||
*p = '\\';
|
||||
*p = *body_pointer;
|
||||
}
|
||||
trans_char = 0;
|
||||
} else {
|
||||
*p = *body_pointer;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
*p = 0;
|
||||
hosts[pos] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(pos = 0; pos < host_num; pos++)
|
||||
{
|
||||
if(strcmp(phost[pos], host) == 0)
|
||||
{
|
||||
is_match = 1;
|
||||
local->host_matched = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(is_match == 0)
|
||||
{
|
||||
free(local->recv_buffer);
|
||||
local->recv_buffer = malloc(0);
|
||||
local->recv_buffer_size = 0;
|
||||
local->has_sent_header = 1;
|
||||
local->has_recv_header = 1;
|
||||
LOGE("http_simple: not match host, host: %s", host);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(host);
|
||||
}
|
||||
}
|
||||
|
||||
if(ret_buf_len <= 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
data_begin += 4;
|
||||
local->has_recv_header = 1;
|
||||
|
||||
ret_buf = (char*)realloc(ret_buf, ret_buf_len + datalength - (data_begin - encryptdata));
|
||||
outlength = ret_buf_len + datalength - (data_begin - encryptdata);
|
||||
|
||||
memcpy(ret_buf + ret_buf_len, data_begin, datalength - (data_begin - encryptdata));
|
||||
|
||||
if (*capacity < outlength) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
|
||||
memcpy(encryptdata, ret_buf, outlength);
|
||||
free(ret_buf);
|
||||
return outlength;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void boundary(char result[])
|
||||
{
|
||||
char *str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
int i,lstr;
|
||||
char ss[3] = {0};
|
||||
lstr = strlen(str);
|
||||
srand((unsigned int)time((time_t *)NULL));
|
||||
for(i = 0; i < 32; ++i)
|
||||
{
|
||||
sprintf(ss, "%c", str[(rand()%lstr)]);
|
||||
strcat(result, ss);
|
||||
}
|
||||
}
|
||||
|
||||
int http_post_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
http_simple_local_data *local = (http_simple_local_data*)self->l_data;
|
||||
if (local->has_sent_header) {
|
||||
return datalength;
|
||||
}
|
||||
char hosts[1024];
|
||||
char * phost[128];
|
||||
int host_num = 0;
|
||||
int pos;
|
||||
char hostport[128];
|
||||
int head_size = self->server.head_len + (xorshift128plus() & 0x3F);
|
||||
int outlength;
|
||||
char * out_buffer = (char*)malloc(datalength + 2048);
|
||||
char * body_buffer = NULL;
|
||||
if (head_size > datalength)
|
||||
head_size = datalength;
|
||||
http_simple_encode_head(local, encryptdata, head_size);
|
||||
if (self->server.param && strlen(self->server.param) == 0)
|
||||
self->server.param = NULL;
|
||||
strncpy(hosts, self->server.param ? self->server.param : self->server.host, sizeof hosts);
|
||||
phost[host_num++] = hosts;
|
||||
for (pos = 0; hosts[pos]; ++pos) {
|
||||
if (hosts[pos] == ',') {
|
||||
phost[host_num++] = &hosts[pos + 1];
|
||||
hosts[pos] = 0;
|
||||
} else if (hosts[pos] == '#') {
|
||||
char * body_pointer = &hosts[pos + 1];
|
||||
char * p;
|
||||
int trans_char = 0;
|
||||
p = body_buffer = (char*)malloc(2048);
|
||||
for ( ; *body_pointer; ++body_pointer) {
|
||||
if (*body_pointer == '\\') {
|
||||
trans_char = 1;
|
||||
continue;
|
||||
} else if (*body_pointer == '\n') {
|
||||
*p = '\r';
|
||||
*++p = '\n';
|
||||
continue;
|
||||
}
|
||||
if (trans_char) {
|
||||
if (*body_pointer == '\\' ) {
|
||||
*p = '\\';
|
||||
} else if (*body_pointer == 'n' ) {
|
||||
*p = '\r';
|
||||
*++p = '\n';
|
||||
} else {
|
||||
*p = '\\';
|
||||
*p = *body_pointer;
|
||||
}
|
||||
trans_char = 0;
|
||||
} else {
|
||||
*p = *body_pointer;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
*p = 0;
|
||||
hosts[pos] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
host_num = xorshift128plus() % host_num;
|
||||
if (self->server.port == 80)
|
||||
sprintf(hostport, "%s", phost[host_num]);
|
||||
else
|
||||
sprintf(hostport, "%s:%d", phost[host_num], self->server.port);
|
||||
if (body_buffer) {
|
||||
sprintf(out_buffer,
|
||||
"POST /%s HTTP/1.1\r\n"
|
||||
"Host: %s\r\n"
|
||||
"%s\r\n\r\n",
|
||||
local->encode_buffer,
|
||||
hostport,
|
||||
body_buffer);
|
||||
} else {
|
||||
char result[33] = {0};
|
||||
boundary(result);
|
||||
sprintf(out_buffer,
|
||||
"POST /%s HTTP/1.1\r\n"
|
||||
"Host: %s\r\n"
|
||||
"User-Agent: %s\r\n"
|
||||
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"
|
||||
"Accept-Language: en-US,en;q=0.8\r\n"
|
||||
"Accept-Encoding: gzip, deflate\r\n"
|
||||
"Content-Type: multipart/form-data; boundary=%s\r\n"
|
||||
"DNT: 1\r\n"
|
||||
"Connection: keep-alive\r\n"
|
||||
"\r\n",
|
||||
local->encode_buffer,
|
||||
hostport,
|
||||
g_useragent[g_useragent_index],
|
||||
result
|
||||
);
|
||||
}
|
||||
//LOGI("http header: %s", out_buffer);
|
||||
outlength = strlen(out_buffer);
|
||||
memmove(out_buffer + outlength, encryptdata + head_size, datalength - head_size);
|
||||
outlength += datalength - head_size;
|
||||
local->has_sent_header = 1;
|
||||
if (*capacity < outlength) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memmove(encryptdata, out_buffer, outlength);
|
||||
free(out_buffer);
|
||||
if (body_buffer != NULL)
|
||||
free(body_buffer);
|
||||
if (local->encode_buffer != NULL) {
|
||||
free(local->encode_buffer);
|
||||
local->encode_buffer = NULL;
|
||||
}
|
||||
return outlength;
|
||||
}
|
21
shadowsocksr-libev/src/server/http_simple.h
Normal file
21
shadowsocksr-libev/src/server/http_simple.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* http_simple.h - Define shadowsocksR server's buffers and callbacks
|
||||
*
|
||||
* Copyright (C) 2015 - 2016, Break Wa11 <mmgac001@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _HTTP_SIMPLE_H
|
||||
#define _HTTP_SIMPLE_H
|
||||
|
||||
obfs * http_simple_new_obfs();
|
||||
void http_simple_dispose(obfs *self);
|
||||
|
||||
int http_simple_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity);
|
||||
int http_simple_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback);
|
||||
|
||||
int http_post_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity);
|
||||
|
||||
int http_simple_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity);
|
||||
int http_simple_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback);
|
||||
|
||||
#endif // _HTTP_SIMPLE_H
|
260
shadowsocksr-libev/src/server/jconf.c
Normal file
260
shadowsocksr-libev/src/server/jconf.c
Normal file
@ -0,0 +1,260 @@
|
||||
/*
|
||||
* jconf.c - Parse the JSON format config file
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* This file is part of the shadowsocks-libev.
|
||||
* shadowsocks-libev is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* shadowsocks-libev is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with shadowsocks-libev; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "jconf.h"
|
||||
#include "json.h"
|
||||
#include "string.h"
|
||||
|
||||
#include <libcork/core.h>
|
||||
|
||||
#define check_json_value_type(value, expected_type, message) \
|
||||
do { \
|
||||
if ((value)->type != (expected_type)) \
|
||||
FATAL((message)); \
|
||||
} while(0)
|
||||
|
||||
static char *
|
||||
to_string(const json_value *value)
|
||||
{
|
||||
if (value->type == json_string) {
|
||||
return ss_strndup(value->u.string.ptr, value->u.string.length);
|
||||
} else if (value->type == json_integer) {
|
||||
return strdup(ss_itoa(value->u.integer));
|
||||
} else if (value->type == json_null) {
|
||||
return "null";
|
||||
} else {
|
||||
LOGE("%d", value->type);
|
||||
FATAL("Invalid config format.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
free_addr(ss_addr_t *addr)
|
||||
{
|
||||
ss_free(addr->host);
|
||||
ss_free(addr->port);
|
||||
}
|
||||
|
||||
void
|
||||
parse_addr(const char *str, ss_addr_t *addr)
|
||||
{
|
||||
int ipv6 = 0, ret = -1, n = 0;
|
||||
char *pch;
|
||||
|
||||
struct cork_ip ip;
|
||||
if (cork_ip_init(&ip, str) != -1) {
|
||||
addr->host = strdup(str);
|
||||
addr->port = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
pch = strchr(str, ':');
|
||||
while (pch != NULL) {
|
||||
n++;
|
||||
ret = pch - str;
|
||||
pch = strchr(pch + 1, ':');
|
||||
}
|
||||
if (n > 1) {
|
||||
ipv6 = 1;
|
||||
if (str[ret - 1] != ']') {
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == -1) {
|
||||
if (ipv6) {
|
||||
addr->host = ss_strndup(str + 1, strlen(str) - 2);
|
||||
} else {
|
||||
addr->host = strdup(str);
|
||||
}
|
||||
addr->port = NULL;
|
||||
} else {
|
||||
if (ipv6) {
|
||||
addr->host = ss_strndup(str + 1, ret - 2);
|
||||
} else {
|
||||
addr->host = ss_strndup(str, ret);
|
||||
}
|
||||
addr->port = strdup(str + ret + 1);
|
||||
}
|
||||
}
|
||||
|
||||
jconf_t *
|
||||
read_jconf(const char *file)
|
||||
{
|
||||
static jconf_t conf;
|
||||
|
||||
memset(&conf, 0, sizeof(jconf_t));
|
||||
|
||||
char *buf;
|
||||
json_value *obj;
|
||||
|
||||
FILE *f = fopen(file, "rb");
|
||||
if (f == NULL) {
|
||||
FATAL("Invalid config path.");
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
long pos = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
if (pos >= MAX_CONF_SIZE) {
|
||||
FATAL("Too large config file.");
|
||||
}
|
||||
|
||||
buf = ss_malloc(pos + 1);
|
||||
if (buf == NULL) {
|
||||
FATAL("No enough memory.");
|
||||
}
|
||||
|
||||
int nread = fread(buf, pos, 1, f);
|
||||
if (!nread) {
|
||||
FATAL("Failed to read the config file.");
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
buf[pos] = '\0'; // end of string
|
||||
|
||||
json_settings settings = { 0UL, 0, NULL, NULL, NULL };
|
||||
char error_buf[512];
|
||||
obj = json_parse_ex(&settings, buf, pos, error_buf);
|
||||
|
||||
if (obj == NULL) {
|
||||
FATAL(error_buf);
|
||||
}
|
||||
|
||||
if (obj->type == json_object) {
|
||||
unsigned int i, j;
|
||||
for (i = 0; i < obj->u.object.length; i++) {
|
||||
char *name = obj->u.object.values[i].name;
|
||||
json_value *value = obj->u.object.values[i].value;
|
||||
if (strcmp(name, "server") == 0) {
|
||||
if (value->type == json_array) {
|
||||
for (j = 0; j < value->u.array.length; j++) {
|
||||
if (j >= MAX_REMOTE_NUM) {
|
||||
break;
|
||||
}
|
||||
json_value *v = value->u.array.values[j];
|
||||
char *addr_str = to_string(v);
|
||||
parse_addr(addr_str, conf.remote_addr + j);
|
||||
ss_free(addr_str);
|
||||
conf.remote_num = j + 1;
|
||||
}
|
||||
} else if (value->type == json_string) {
|
||||
conf.remote_addr[0].host = to_string(value);
|
||||
conf.remote_addr[0].port = NULL;
|
||||
conf.remote_num = 1;
|
||||
}
|
||||
} else if (strcmp(name, "port_password") == 0) {
|
||||
if (value->type == json_object) {
|
||||
for (j = 0; j < value->u.object.length; j++) {
|
||||
if (j >= MAX_PORT_NUM) {
|
||||
break;
|
||||
}
|
||||
json_value *v = value->u.object.values[j].value;
|
||||
if (v->type == json_string) {
|
||||
conf.port_password[j].port = ss_strndup(value->u.object.values[j].name,
|
||||
value->u.object.values[j].name_length);
|
||||
conf.port_password[j].password = to_string(v);
|
||||
conf.port_password_num = j + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (strcmp(name, "server_port") == 0) {
|
||||
conf.remote_port = to_string(value);
|
||||
} else if (strcmp(name, "local_address") == 0) {
|
||||
conf.local_addr = to_string(value);
|
||||
} else if (strcmp(name, "local_port") == 0) {
|
||||
conf.local_port = to_string(value);
|
||||
} else if (strcmp(name, "password") == 0) {
|
||||
conf.password = to_string(value);
|
||||
} else if (strcmp(name, "protocol") == 0) { // SSR
|
||||
conf.protocol = to_string(value);
|
||||
} else if (strcmp(name, "protocol_param") == 0) { // SSR
|
||||
conf.protocol_param = to_string(value);
|
||||
} else if (strcmp(name, "method") == 0) {
|
||||
conf.method = to_string(value);
|
||||
} else if (strcmp(name, "obfs") == 0) { // SSR
|
||||
conf.obfs = to_string(value);
|
||||
} else if (strcmp(name, "obfs_param") == 0) { // SSR
|
||||
conf.obfs_param = to_string(value);
|
||||
} else if (strcmp(name, "timeout") == 0) {
|
||||
conf.timeout = to_string(value);
|
||||
} else if (strcmp(name, "user") == 0) {
|
||||
conf.user = to_string(value);
|
||||
} else if (strcmp(name, "fast_open") == 0) {
|
||||
check_json_value_type(value, json_boolean,
|
||||
"invalid config file: option 'fast_open' must be a boolean");
|
||||
conf.fast_open = value->u.boolean;
|
||||
} else if (strcmp(name, "auth") == 0) {
|
||||
check_json_value_type(value, json_boolean,
|
||||
"invalid config file: option 'auth' must be a boolean");
|
||||
conf.auth = value->u.boolean;
|
||||
} else if (strcmp(name, "nofile") == 0) {
|
||||
check_json_value_type(value, json_integer,
|
||||
"invalid config file: option 'nofile' must be an integer");
|
||||
conf.nofile = value->u.integer;
|
||||
} else if (strcmp(name, "nameserver") == 0) {
|
||||
conf.nameserver = to_string(value);
|
||||
} else if (strcmp(name, "tunnel_address") == 0) {
|
||||
conf.tunnel_address = to_string(value);
|
||||
} else if (strcmp(name, "mode") == 0) {
|
||||
char *mode_str = to_string(value);
|
||||
|
||||
if (strcmp(mode_str, "tcp_only") == 0)
|
||||
conf.mode = TCP_ONLY;
|
||||
else if (strcmp(mode_str, "tcp_and_udp") == 0)
|
||||
conf.mode = TCP_AND_UDP;
|
||||
else if (strcmp(mode_str, "udp_only") == 0)
|
||||
conf.mode = UDP_ONLY;
|
||||
else
|
||||
LOGI("ignore unknown mode: %s, use tcp_only as fallback",
|
||||
mode_str);
|
||||
ss_free(mode_str);
|
||||
} else if (strcmp(name, "mtu") == 0) {
|
||||
check_json_value_type(value, json_integer,
|
||||
"invalid config file: option 'mtu' must be an integer");
|
||||
conf.mtu = value->u.integer;
|
||||
} else if (strcmp(name, "mptcp") == 0) {
|
||||
check_json_value_type(value, json_boolean,
|
||||
"invalid config file: option 'mptcp' must be a boolean");
|
||||
conf.mptcp = value->u.boolean;
|
||||
} else if (strcmp(name, "ipv6_first") == 0) {
|
||||
check_json_value_type(value, json_boolean,
|
||||
"invalid config file: option 'ipv6_first' must be a boolean");
|
||||
conf.ipv6_first = value->u.boolean;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FATAL("Invalid config file");
|
||||
}
|
||||
|
||||
ss_free(buf);
|
||||
json_value_free(obj);
|
||||
return &conf;
|
||||
}
|
78
shadowsocksr-libev/src/server/jconf.h
Normal file
78
shadowsocksr-libev/src/server/jconf.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* jconf.h - Define the config data structure
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* This file is part of the shadowsocks-libev.
|
||||
* shadowsocks-libev is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* shadowsocks-libev is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with shadowsocks-libev; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _JCONF_H
|
||||
#define _JCONF_H
|
||||
|
||||
#define MAX_PORT_NUM 1024
|
||||
#define MAX_REMOTE_NUM 10
|
||||
#define MAX_CONF_SIZE 128 * 1024
|
||||
#define MAX_DNS_NUM 4
|
||||
#define MAX_CONNECT_TIMEOUT 10
|
||||
#define MAX_REQUEST_TIMEOUT 60
|
||||
#define MIN_UDP_TIMEOUT 10
|
||||
|
||||
#define TCP_ONLY 0
|
||||
#define TCP_AND_UDP 1
|
||||
#define UDP_ONLY 3
|
||||
|
||||
typedef struct {
|
||||
char *host;
|
||||
char *port;
|
||||
} ss_addr_t;
|
||||
|
||||
typedef struct {
|
||||
char *port;
|
||||
char *password;
|
||||
} ss_port_password_t;
|
||||
|
||||
typedef struct {
|
||||
int remote_num;
|
||||
ss_addr_t remote_addr[MAX_REMOTE_NUM];
|
||||
int port_password_num;
|
||||
ss_port_password_t port_password[MAX_PORT_NUM];
|
||||
char *remote_port;
|
||||
char *local_addr;
|
||||
char *local_port;
|
||||
char *password;
|
||||
char *protocol; // SSR
|
||||
char *protocol_param; // SSR
|
||||
char *method;
|
||||
char *obfs; // SSR
|
||||
char *obfs_param; // SSR
|
||||
char *timeout;
|
||||
char *user;
|
||||
int auth;
|
||||
int fast_open;
|
||||
int nofile;
|
||||
char *nameserver;
|
||||
char *tunnel_address;
|
||||
int mode;
|
||||
int mtu;
|
||||
int mptcp;
|
||||
int ipv6_first;
|
||||
} jconf_t;
|
||||
|
||||
jconf_t *read_jconf(const char *file);
|
||||
void parse_addr(const char *str, ss_addr_t *addr);
|
||||
void free_addr(ss_addr_t *addr);
|
||||
|
||||
#endif // _JCONF_H
|
1002
shadowsocksr-libev/src/server/json.c
Normal file
1002
shadowsocksr-libev/src/server/json.c
Normal file
File diff suppressed because it is too large
Load Diff
249
shadowsocksr-libev/src/server/json.h
Normal file
249
shadowsocksr-libev/src/server/json.h
Normal file
@ -0,0 +1,249 @@
|
||||
/* vim: set et ts=3 sw=3 sts=3 ft=c:
|
||||
*
|
||||
* Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
|
||||
* https://github.com/udp/json-parser
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _JSON_H
|
||||
#define _JSON_H
|
||||
|
||||
#ifndef json_char
|
||||
#define json_char char
|
||||
#endif
|
||||
|
||||
#ifndef json_int_t
|
||||
#ifndef _MSC_VER
|
||||
#include <inttypes.h>
|
||||
#define json_int_t int64_t
|
||||
#else
|
||||
#define json_int_t __int64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <string.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned long max_memory;
|
||||
int settings;
|
||||
|
||||
/* Custom allocator support (leave null to use malloc/free)
|
||||
*/
|
||||
|
||||
void * (*mem_alloc)(size_t, int zero, void *user_data);
|
||||
void (*mem_free)(void *, void *user_data);
|
||||
|
||||
void *user_data; /* will be passed to mem_alloc and mem_free */
|
||||
} json_settings;
|
||||
|
||||
#define json_enable_comments 0x01
|
||||
|
||||
typedef enum {
|
||||
json_none,
|
||||
json_object,
|
||||
json_array,
|
||||
json_integer,
|
||||
json_double,
|
||||
json_string,
|
||||
json_boolean,
|
||||
json_null
|
||||
} json_type;
|
||||
|
||||
extern const struct _json_value json_value_none;
|
||||
|
||||
typedef struct _json_value {
|
||||
struct _json_value *parent;
|
||||
|
||||
json_type type;
|
||||
|
||||
union {
|
||||
int boolean;
|
||||
json_int_t integer;
|
||||
double dbl;
|
||||
|
||||
struct {
|
||||
unsigned int length;
|
||||
json_char *ptr; /* null terminated */
|
||||
} string;
|
||||
|
||||
struct {
|
||||
unsigned int length;
|
||||
|
||||
struct {
|
||||
json_char *name;
|
||||
unsigned int name_length;
|
||||
|
||||
struct _json_value *value;
|
||||
} *values;
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
decltype(values) begin() const
|
||||
{
|
||||
return values;
|
||||
}
|
||||
decltype(values) end() const
|
||||
{
|
||||
return values + length;
|
||||
}
|
||||
#endif
|
||||
} object;
|
||||
|
||||
struct {
|
||||
unsigned int length;
|
||||
struct _json_value **values;
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
decltype(values) begin() const
|
||||
{
|
||||
return values;
|
||||
}
|
||||
decltype(values) end() const
|
||||
{
|
||||
return values + length;
|
||||
}
|
||||
#endif
|
||||
} array;
|
||||
} u;
|
||||
|
||||
union {
|
||||
struct _json_value *next_alloc;
|
||||
void *object_mem;
|
||||
} _reserved;
|
||||
|
||||
/* Some C++ operator sugar */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
public:
|
||||
|
||||
inline _json_value(){
|
||||
memset(this, 0, sizeof(_json_value));
|
||||
}
|
||||
|
||||
inline const struct _json_value &operator [] (int index) const {
|
||||
if (type != json_array || index < 0
|
||||
|| ((unsigned int)index) >= u.array.length) {
|
||||
return json_value_none;
|
||||
}
|
||||
|
||||
return *u.array.values[index];
|
||||
}
|
||||
|
||||
inline const struct _json_value &operator [] (const char *index) const {
|
||||
if (type != json_object) {
|
||||
return json_value_none;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < u.object.length; ++i)
|
||||
if (!strcmp(u.object.values[i].name, index)) {
|
||||
return *u.object.values[i].value;
|
||||
}
|
||||
|
||||
return json_value_none;
|
||||
}
|
||||
|
||||
inline operator const char * () const
|
||||
{
|
||||
switch (type) {
|
||||
case json_string:
|
||||
return u.string.ptr;
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
inline operator
|
||||
json_int_t() const
|
||||
{
|
||||
switch (type) {
|
||||
case json_integer:
|
||||
return u.integer;
|
||||
|
||||
case json_double:
|
||||
return (json_int_t)u.dbl;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline operator
|
||||
bool() const
|
||||
{
|
||||
if (type != json_boolean) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return u.boolean != 0;
|
||||
}
|
||||
|
||||
inline operator double () const
|
||||
{
|
||||
switch (type) {
|
||||
case json_integer:
|
||||
return (double)u.integer;
|
||||
|
||||
case json_double:
|
||||
return u.dbl;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
} json_value;
|
||||
|
||||
json_value *json_parse(const json_char *json,
|
||||
size_t length);
|
||||
|
||||
#define json_error_max 128
|
||||
json_value *json_parse_ex(json_settings *settings,
|
||||
const json_char *json,
|
||||
size_t length,
|
||||
char *error);
|
||||
|
||||
void json_value_free(json_value *);
|
||||
|
||||
/* Not usually necessary, unless you used a custom mem_alloc and now want to
|
||||
* use a custom mem_free.
|
||||
*/
|
||||
void json_value_free_ex(json_settings *settings,
|
||||
json_value *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
370
shadowsocksr-libev/src/server/list.c
Normal file
370
shadowsocksr-libev/src/server/list.c
Normal file
@ -0,0 +1,370 @@
|
||||
#include "list.h"
|
||||
|
||||
/// 文件:list_impl.c
|
||||
/// 功能:实现链表的基本操作
|
||||
/// 作者:bluewind
|
||||
/// 完成时间:2011.5.29
|
||||
/// 修改时间:2011.5.31, 2011.7.2
|
||||
/// 修改备注:在头节点处添加一个空节点,可以优化添加、删除节点代码
|
||||
/// 再次修改,链表增加节点数据data_size,限制数据大小,修改了
|
||||
/// 添加复制数据代码,修正重复添加节点后释放节点的Bug,添加了前
|
||||
/// 插、排序和遍历功能,7.3 添加tail尾指针,改进后插法性能,并改名
|
||||
/// --------------------------------------------------------------
|
||||
|
||||
void swap_data(Node n1, Node n2);
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_init
|
||||
// 功能: 链表初始化
|
||||
// 参数: 无
|
||||
// 返回值:已初始化链表指针
|
||||
// 备注: 链表本身动态分配,由list_destroy函数管理释放
|
||||
/// --------------------------------------------------------------
|
||||
List list_init(unsigned int data_size)
|
||||
{
|
||||
List list = (List) malloc(sizeof(struct clist));
|
||||
if(list != NULL) //内存分配成功
|
||||
{
|
||||
list->head = (Node) malloc(sizeof(node)); //为头节点分配内存
|
||||
if(list->head) //内存分配成功
|
||||
{
|
||||
list->head->data = NULL; //初始化头节点
|
||||
list->head->next = NULL;
|
||||
list->data_size = data_size;
|
||||
list->tail = list->head;
|
||||
list->size = 0;
|
||||
|
||||
list->add_back = list_add_back; //初始化成员函数
|
||||
list->add_front = list_add_front;
|
||||
list->delete_node = list_delete_node;
|
||||
list->delete_at = list_delete_at;
|
||||
list->modify_at = list_modify_at;
|
||||
list->have_same = list_have_same;
|
||||
list->have_same_cmp = list_have_same_cmp;
|
||||
list->foreach = list_foreach;
|
||||
list->clear = list_clear;
|
||||
list->sort = list_sort;
|
||||
list->destroy = list_destroy;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_add_back
|
||||
// 功能: 添加链表结点 (后插法)
|
||||
// 参数: l--链表指针,data--链表数据指针,可为任意类型
|
||||
// 返回值:int型,为1表示添加成功,为0表示添加失败
|
||||
// 备注: 如果链表本身为空或是分配节点内存失败,将返回0
|
||||
/// --------------------------------------------------------------
|
||||
int list_add_back(List l, void *data)
|
||||
{
|
||||
Node new_node = (Node) malloc(sizeof(node));
|
||||
|
||||
if(l != NULL && new_node != NULL) //链表本身不为空,且内存申请成功
|
||||
{
|
||||
new_node->data = malloc(l->data_size);
|
||||
memcpy(new_node->data, data, l->data_size);
|
||||
new_node->next = NULL;
|
||||
|
||||
l->tail->next = new_node; //添加节点
|
||||
l->tail = new_node; //记录尾节点位置
|
||||
l->size ++; //链表元素总数加1
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_add_front
|
||||
// 功能: 添加链表结点 (前插法)
|
||||
// 参数: l--链表指针,data--链表数据指针,可为任意类型
|
||||
// 返回值:int型,为1表示添加成功,为0表示添加失败
|
||||
// 备注: 如果链表本身为空或是分配节点内存失败,将返回0
|
||||
/// --------------------------------------------------------------
|
||||
int list_add_front(List l, void *data)
|
||||
{
|
||||
Node new_node = (Node) malloc(sizeof(node));
|
||||
|
||||
if(l != NULL && new_node != NULL)
|
||||
{
|
||||
new_node->data = malloc(l->data_size);
|
||||
memcpy(new_node->data, data, l->data_size);
|
||||
new_node->next = l->head->next;
|
||||
|
||||
l->head->next = new_node;
|
||||
if(!l->size) //记录尾指针位置
|
||||
l->tail = new_node;
|
||||
l->size ++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_delete_node
|
||||
// 功能:删除链表结点
|
||||
// 参数:l--链表指针,data--链表数据指针,可为任意类型
|
||||
// *pfunc为指向一个数据类型比较的函数指针
|
||||
// 返回值:int型,为1表示删除成功,为0表示没有找到匹配数据
|
||||
// 备注:*pfunc函数接口参数ndata为节点数据,data为比较数据,返回为真表示匹配数据
|
||||
/// --------------------------------------------------------------
|
||||
int list_delete_node(List l, void *data, int (*pfunc)(void *ndata, void *data))
|
||||
{
|
||||
if(l != NULL)
|
||||
{
|
||||
Node prev = l->head; //前一个节点
|
||||
Node curr = l->head->next; //当前节点
|
||||
|
||||
while(curr != NULL)
|
||||
{
|
||||
if(pfunc(curr->data, data)) //如果找到匹配数据
|
||||
{
|
||||
if(curr == l->tail) //如果是删除尾节点
|
||||
l->tail = prev;
|
||||
|
||||
prev->next = prev->next->next; //修改前节点next指针指向下下个节点
|
||||
|
||||
free(curr->data); //释放节点数据
|
||||
free(curr); //释放节点
|
||||
|
||||
l->size--; //链表元素总数减1
|
||||
return 1; //返回真值
|
||||
}
|
||||
prev = prev->next; //没有找到匹配时移动前节点和当前节点
|
||||
curr = curr->next;
|
||||
}
|
||||
}
|
||||
|
||||
return 0; //没有找到匹配数据
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_delete_at
|
||||
// 功能: 修改链表节点元素值
|
||||
// 参数: l--链表指针,index--索引值, 范围(0 -- size-1)
|
||||
// 返回值:int型,为1表示删除成功,为0表示删除失败
|
||||
// 备注: 如果链表本身为空或是index为非法值,将返回0
|
||||
/// --------------------------------------------------------------
|
||||
int list_delete_at(List l, unsigned int index)
|
||||
{
|
||||
unsigned int cindex = 0;
|
||||
|
||||
if(l != NULL && index >= 0 && index < l->size)
|
||||
{
|
||||
Node prev = l->head; //前一个节点
|
||||
Node curr = l->head->next; //当前节点
|
||||
|
||||
while(cindex != index)
|
||||
{
|
||||
prev = prev->next;
|
||||
curr = curr->next;
|
||||
cindex ++;
|
||||
}
|
||||
|
||||
if(index == (l->size) - 1)
|
||||
l->tail = prev;
|
||||
|
||||
prev->next = prev->next->next;
|
||||
free(curr->data);
|
||||
free(curr);
|
||||
l->size --;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_modify_at
|
||||
// 功能: 修改链表节点元素值
|
||||
// 参数: l--链表指针,index--索引值, 范围(0 -- size-1)
|
||||
// data--链表数据指针
|
||||
// 返回值:int型,为1表示修改成功,为0表示修改失败
|
||||
// 备注: 如果链表本身为空或是index为非法值,将返回0
|
||||
/// --------------------------------------------------------------
|
||||
int list_modify_at(List l, unsigned int index, void *new_data)
|
||||
{
|
||||
unsigned int cindex = 0;
|
||||
|
||||
if(l != NULL && index >= 0 && index < l->size ) //非空链表,并且index值合法
|
||||
{
|
||||
Node curr = l->head->next;
|
||||
while(cindex != index)
|
||||
{
|
||||
curr = curr->next;
|
||||
cindex ++;
|
||||
}
|
||||
memcpy(curr->data, new_data, l->data_size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_sort
|
||||
// 功能: 链表排序
|
||||
// 参数: l--链表指针,*pfunc为指向一个数据类型比较的函数指针
|
||||
// 返回值:无
|
||||
// 备注: 使用简单选择排序法,相比冒泡法每次交换,效率高一点
|
||||
/// --------------------------------------------------------------
|
||||
void list_sort(List l, compare pfunc)
|
||||
{
|
||||
if(l != NULL)
|
||||
{
|
||||
Node min, icurr, jcurr;
|
||||
|
||||
icurr = l->head->next;
|
||||
while(icurr)
|
||||
{
|
||||
min = icurr; //记录最小值
|
||||
jcurr = icurr->next; //内循环指向下一个节点
|
||||
while(jcurr)
|
||||
{
|
||||
if(pfunc(min->data, jcurr->data)) //如果找到n+1到最后一个元素最小值
|
||||
min = jcurr; //记录下最小值的位置
|
||||
|
||||
jcurr = jcurr->next;
|
||||
}
|
||||
|
||||
if(min != icurr) //当最小值位置和n+1元素位置不相同时
|
||||
{
|
||||
swap_data(min, icurr); //才进行交换,减少交换次数
|
||||
}
|
||||
|
||||
icurr = icurr->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void swap_data(Node n1, Node n2)
|
||||
{
|
||||
void *temp;
|
||||
|
||||
temp = n2->data;
|
||||
n2->data = n1->data;
|
||||
n1->data = temp;
|
||||
}
|
||||
|
||||
|
||||
int list_have_same(List l, void *data, int (*pfunc)(void *ndata, void *data))
|
||||
{
|
||||
if(l != NULL)
|
||||
{
|
||||
Node curr;
|
||||
|
||||
for(curr = l->head->next; curr != NULL; curr = curr->next)
|
||||
{
|
||||
if(pfunc(curr->data, data))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int list_have_same_cmp(List l, void *data)
|
||||
{
|
||||
if(l != NULL)
|
||||
{
|
||||
Node curr;
|
||||
|
||||
for(curr = l->head->next; curr != NULL; curr = curr->next)
|
||||
{
|
||||
if(memcmp(curr->data, data, l->data_size))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_foreach
|
||||
// 功能: 遍历链表元素
|
||||
// 参数: l--链表指针,doit为指向一个处理数据的函数指针
|
||||
// 返回值:无
|
||||
// 备注: doit申明为void (*dofunc)(void *ndata)原型
|
||||
/// --------------------------------------------------------------
|
||||
void list_foreach(List l, dofunc doit)
|
||||
{
|
||||
if(l != NULL)
|
||||
{
|
||||
Node curr;
|
||||
|
||||
for(curr = l->head->next; curr != NULL; curr = curr->next)
|
||||
{
|
||||
doit(curr->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_clear
|
||||
// 功能: 清空链表元素
|
||||
// 参数: l--链表指针
|
||||
// 返回值:无
|
||||
// 备注: 没有使用先Destroy再Init链表的办法,直接实现
|
||||
/// --------------------------------------------------------------
|
||||
void list_clear(List l)
|
||||
{
|
||||
if(l != NULL)
|
||||
{
|
||||
Node temp;
|
||||
Node curr = l->head->next;
|
||||
|
||||
while(curr != NULL)
|
||||
{
|
||||
temp = curr->next;
|
||||
|
||||
free(curr->data); //释放节点和数据
|
||||
free(curr);
|
||||
|
||||
curr = temp;
|
||||
}
|
||||
|
||||
l->size = 0; //重置链表数据
|
||||
l->head->next = NULL;
|
||||
l->tail = l->head;
|
||||
}
|
||||
}
|
||||
|
||||
/// --------------------------------------------------------------
|
||||
// 函数名:list_destroy
|
||||
// 功能: 释放链表
|
||||
// 参数: l--链表指针
|
||||
// 返回值:空链表指针
|
||||
/// --------------------------------------------------------------
|
||||
List list_destroy(List l)
|
||||
{
|
||||
if(l != NULL)
|
||||
{
|
||||
Node temp;
|
||||
|
||||
while(l->head)
|
||||
{
|
||||
temp = l->head->next;
|
||||
|
||||
if(l->head->data != NULL) //如果是头节点就不释放数据空间
|
||||
free(l->head->data); //先释放节点数据(但是节点数据里也有指针?)
|
||||
free(l->head); //再释放节点
|
||||
|
||||
l->head = temp;
|
||||
}
|
||||
|
||||
free(l); //释放链表本身占用空间
|
||||
l = NULL;
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
61
shadowsocksr-libev/src/server/list.h
Normal file
61
shadowsocksr-libev/src/server/list.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef LIST_H_H
|
||||
#define LIST_H_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct clist *List;
|
||||
|
||||
typedef int (*compare)(void *ndata, void *data);
|
||||
typedef void (*dofunc)(void *ndata);
|
||||
|
||||
typedef int (*lpf0)(List l, void *data);
|
||||
typedef int (*lpf1)(List l, void *data, compare pfunc);
|
||||
typedef List (*lpf2)(List l);
|
||||
typedef void (*lpf3)(List l);
|
||||
typedef void (*lpf4)(List l, dofunc pfunc);
|
||||
typedef int (*lpf5)(List l, unsigned int index, void *new_data);
|
||||
typedef void (*lpf6)(List l, compare pfunc);
|
||||
typedef int (*lpf7)(List l, unsigned int index);
|
||||
|
||||
typedef struct cnode
|
||||
{
|
||||
void *data;
|
||||
struct cnode *next;
|
||||
}node, *Node;
|
||||
|
||||
typedef struct clist
|
||||
{
|
||||
Node head;
|
||||
Node tail;
|
||||
unsigned int size;
|
||||
unsigned int data_size;
|
||||
lpf0 add_back;
|
||||
lpf0 add_front;
|
||||
lpf1 delete_node;
|
||||
lpf1 have_same;
|
||||
lpf0 have_same_cmp;
|
||||
lpf4 foreach;
|
||||
lpf3 clear;
|
||||
lpf2 destroy;
|
||||
lpf5 modify_at;
|
||||
lpf6 sort;
|
||||
lpf7 delete_at;
|
||||
}list;
|
||||
|
||||
//初始化链表
|
||||
List list_init(unsigned int data_size);
|
||||
int list_add_back(List l, void *data);
|
||||
int list_add_front(List l, void *data);
|
||||
int list_delete_node(List l, void *data, compare pfunc);
|
||||
int list_delete_at(List l, unsigned int index);
|
||||
int list_modify_at(List l, unsigned int index, void *new_data);
|
||||
int list_have_same(List l, void *data, compare pfunc);
|
||||
int list_have_same_cmp(List l, void *data);
|
||||
void list_foreach(List l, dofunc doit);
|
||||
void list_sort(List l, compare pfunc);
|
||||
void list_clear(List l);
|
||||
//释放链表
|
||||
List list_destroy(List l);
|
||||
#endif
|
297
shadowsocksr-libev/src/server/netutils.c
Normal file
297
shadowsocksr-libev/src/server/netutils.c
Normal file
@ -0,0 +1,297 @@
|
||||
/*
|
||||
* netutils.c - Network utilities
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* This file is part of the shadowsocks-libev.
|
||||
*
|
||||
* shadowsocks-libev is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* shadowsocks-libev is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with shadowsocks-libev; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <libcork/core.h>
|
||||
#include <udns.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include "win32.h"
|
||||
#define sleep(n) Sleep(1000 * (n))
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.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
|
||||
|
||||
#include "netutils.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifndef SO_REUSEPORT
|
||||
#define SO_REUSEPORT 15
|
||||
#endif
|
||||
|
||||
extern int verbose;
|
||||
|
||||
static const char valid_label_bytes[] =
|
||||
"-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
#if defined(MODULE_LOCAL)
|
||||
extern int keep_resolving;
|
||||
#endif
|
||||
|
||||
int
|
||||
set_reuseport(int socket)
|
||||
{
|
||||
int opt = 1;
|
||||
return setsockopt(socket, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
|
||||
}
|
||||
|
||||
size_t
|
||||
get_sockaddr_len(struct sockaddr *addr)
|
||||
{
|
||||
if (addr->sa_family == AF_INET) {
|
||||
return sizeof(struct sockaddr_in);
|
||||
} else if (addr->sa_family == AF_INET6) {
|
||||
return sizeof(struct sockaddr_in6);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SET_INTERFACE
|
||||
int
|
||||
setinterface(int socket_fd, const char *interface_name)
|
||||
{
|
||||
struct ifreq interface;
|
||||
memset(&interface, 0, sizeof(struct ifreq));
|
||||
strncpy(interface.ifr_name, interface_name, IFNAMSIZ);
|
||||
int res = setsockopt(socket_fd, SOL_SOCKET, SO_BINDTODEVICE, &interface,
|
||||
sizeof(struct ifreq));
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int
|
||||
bind_to_address(int socket_fd, const char *host)
|
||||
{
|
||||
if (host != NULL) {
|
||||
struct cork_ip ip;
|
||||
struct sockaddr_storage storage;
|
||||
memset(&storage, 0, sizeof(struct sockaddr_storage));
|
||||
if (cork_ip_init(&ip, host) != -1) {
|
||||
if (ip.version == 4) {
|
||||
struct sockaddr_in *addr = (struct sockaddr_in *)&storage;
|
||||
dns_pton(AF_INET, host, &addr->sin_addr);
|
||||
addr->sin_family = AF_INET;
|
||||
return bind(socket_fd, (struct sockaddr *)addr, sizeof(struct sockaddr_in));
|
||||
} else if (ip.version == 6) {
|
||||
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&storage;
|
||||
dns_pton(AF_INET6, host, &addr->sin6_addr);
|
||||
addr->sin6_family = AF_INET6;
|
||||
return bind(socket_fd, (struct sockaddr *)addr, sizeof(struct sockaddr_in6));
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
get_sockaddr(char *host, char *port,
|
||||
struct sockaddr_storage *storage, int block,
|
||||
int ipv6first)
|
||||
{
|
||||
struct cork_ip ip;
|
||||
if (cork_ip_init(&ip, host) != -1) {
|
||||
if (ip.version == 4) {
|
||||
struct sockaddr_in *addr = (struct sockaddr_in *)storage;
|
||||
addr->sin_family = AF_INET;
|
||||
dns_pton(AF_INET, host, &(addr->sin_addr));
|
||||
if (port != NULL) {
|
||||
addr->sin_port = htons(atoi(port));
|
||||
}
|
||||
} else if (ip.version == 6) {
|
||||
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)storage;
|
||||
addr->sin6_family = AF_INET6;
|
||||
dns_pton(AF_INET6, host, &(addr->sin6_addr));
|
||||
if (port != NULL) {
|
||||
addr->sin6_port = htons(atoi(port));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result, *rp;
|
||||
|
||||
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 */
|
||||
|
||||
int err, i;
|
||||
|
||||
for (i = 1; i < 8; i++) {
|
||||
err = getaddrinfo(host, port, &hints, &result);
|
||||
#if defined(MODULE_LOCAL)
|
||||
if (!keep_resolving)
|
||||
break;
|
||||
#endif
|
||||
if ((!block || !err)) {
|
||||
break;
|
||||
} else {
|
||||
sleep(pow(2, i));
|
||||
LOGE("failed to resolve server name, wait %.0f seconds", pow(2, i));
|
||||
}
|
||||
}
|
||||
|
||||
if (err != 0) {
|
||||
LOGE("getaddrinfo: %s", gai_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
int prefer_af = ipv6first ? AF_INET6 : AF_INET;
|
||||
for (rp = result; rp != NULL; rp = rp->ai_next)
|
||||
if (rp->ai_family == prefer_af) {
|
||||
if (rp->ai_family == AF_INET)
|
||||
memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in));
|
||||
else if (rp->ai_family == AF_INET6)
|
||||
memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in6));
|
||||
break;
|
||||
}
|
||||
|
||||
if (rp == NULL) {
|
||||
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
||||
if (rp->ai_family == AF_INET)
|
||||
memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in));
|
||||
else if (rp->ai_family == AF_INET6)
|
||||
memcpy(storage, rp->ai_addr, sizeof(struct sockaddr_in6));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rp == NULL) {
|
||||
LOGE("failed to resolve remote addr");
|
||||
return -1;
|
||||
}
|
||||
|
||||
freeaddrinfo(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
sockaddr_cmp(struct sockaddr_storage *addr1,
|
||||
struct sockaddr_storage *addr2, socklen_t len)
|
||||
{
|
||||
struct sockaddr_in *p1_in = (struct sockaddr_in *)addr1;
|
||||
struct sockaddr_in *p2_in = (struct sockaddr_in *)addr2;
|
||||
struct sockaddr_in6 *p1_in6 = (struct sockaddr_in6 *)addr1;
|
||||
struct sockaddr_in6 *p2_in6 = (struct sockaddr_in6 *)addr2;
|
||||
if (p1_in->sin_family < p2_in->sin_family)
|
||||
return -1;
|
||||
if (p1_in->sin_family > p2_in->sin_family)
|
||||
return 1;
|
||||
/* compare ip4 */
|
||||
if (p1_in->sin_family == AF_INET) {
|
||||
/* just order it, ntohs not required */
|
||||
if (p1_in->sin_port < p2_in->sin_port)
|
||||
return -1;
|
||||
if (p1_in->sin_port > p2_in->sin_port)
|
||||
return 1;
|
||||
return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);
|
||||
} else if (p1_in6->sin6_family == AF_INET6) {
|
||||
/* just order it, ntohs not required */
|
||||
if (p1_in6->sin6_port < p2_in6->sin6_port)
|
||||
return -1;
|
||||
if (p1_in6->sin6_port > p2_in6->sin6_port)
|
||||
return 1;
|
||||
return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
|
||||
INET6_SIZE);
|
||||
} else {
|
||||
/* eek unknown type, perform this comparison for sanity. */
|
||||
return memcmp(addr1, addr2, len);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
sockaddr_cmp_addr(struct sockaddr_storage *addr1,
|
||||
struct sockaddr_storage *addr2, socklen_t len)
|
||||
{
|
||||
struct sockaddr_in *p1_in = (struct sockaddr_in *)addr1;
|
||||
struct sockaddr_in *p2_in = (struct sockaddr_in *)addr2;
|
||||
struct sockaddr_in6 *p1_in6 = (struct sockaddr_in6 *)addr1;
|
||||
struct sockaddr_in6 *p2_in6 = (struct sockaddr_in6 *)addr2;
|
||||
if (p1_in->sin_family < p2_in->sin_family)
|
||||
return -1;
|
||||
if (p1_in->sin_family > p2_in->sin_family)
|
||||
return 1;
|
||||
/* compare ip4 */
|
||||
if (p1_in->sin_family == AF_INET) {
|
||||
return memcmp(&p1_in->sin_addr, &p2_in->sin_addr, INET_SIZE);
|
||||
} else if (p1_in6->sin6_family == AF_INET6) {
|
||||
return memcmp(&p1_in6->sin6_addr, &p2_in6->sin6_addr,
|
||||
INET6_SIZE);
|
||||
} else {
|
||||
/* eek unknown type, perform this comparison for sanity. */
|
||||
return memcmp(addr1, addr2, len);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
validate_hostname(const char *hostname, const int hostname_len)
|
||||
{
|
||||
if (hostname == NULL)
|
||||
return 0;
|
||||
|
||||
if (hostname_len < 1 || hostname_len > 255)
|
||||
return 0;
|
||||
|
||||
if (hostname[0] == '.')
|
||||
return 0;
|
||||
|
||||
const char *label = hostname;
|
||||
while (label < hostname + hostname_len) {
|
||||
size_t label_len = hostname_len - (label - hostname);
|
||||
char *next_dot = strchr(label, '.');
|
||||
if (next_dot != NULL)
|
||||
label_len = next_dot - label;
|
||||
|
||||
if (label + label_len > hostname + hostname_len)
|
||||
return 0;
|
||||
|
||||
if (label_len > 63 || label_len < 1)
|
||||
return 0;
|
||||
|
||||
if (label[0] == '-' || label[label_len - 1] == '-')
|
||||
return 0;
|
||||
|
||||
if (strspn(label, valid_label_bytes) < label_len)
|
||||
return 0;
|
||||
|
||||
label += label_len + 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
98
shadowsocksr-libev/src/server/netutils.h
Normal file
98
shadowsocksr-libev/src/server/netutils.h
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* netutils.h - Network utilities
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* This file is part of the shadowsocks-libev.
|
||||
*
|
||||
* shadowsocks-libev is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* shadowsocks-libev is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with shadowsocks-libev; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _NETUTILS_H
|
||||
#define _NETUTILS_H
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <netdb.h>
|
||||
#elif !defined(__MINGW32__)
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
|
||||
// only enable TCP_FASTOPEN on linux
|
||||
#if defined(__linux__)
|
||||
#include <linux/tcp.h>
|
||||
/* conditional define for TCP_FASTOPEN */
|
||||
#ifndef TCP_FASTOPEN
|
||||
#define TCP_FASTOPEN 23
|
||||
#endif
|
||||
/* conditional define for MSG_FASTOPEN */
|
||||
#ifndef MSG_FASTOPEN
|
||||
#define MSG_FASTOPEN 0x20000000
|
||||
#endif
|
||||
#elif !defined(__APPLE__)
|
||||
#ifdef TCP_FASTOPEN
|
||||
#undef TCP_FASTOPEN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Backward compatibility for MPTCP_ENABLED between kernel 3 & 4 */
|
||||
#ifndef MPTCP_ENABLED
|
||||
#ifdef TCP_CC_INFO
|
||||
#define MPTCP_ENABLED 42
|
||||
#else
|
||||
#define MPTCP_ENABLED 26
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** byte size of ip4 address */
|
||||
#define INET_SIZE 4
|
||||
/** byte size of ip6 address */
|
||||
#define INET6_SIZE 16
|
||||
|
||||
size_t get_sockaddr_len(struct sockaddr *addr);
|
||||
ssize_t get_sockaddr(char *host, char *port,
|
||||
struct sockaddr_storage *storage, int block,
|
||||
int ipv6first);
|
||||
int set_reuseport(int socket);
|
||||
|
||||
#ifdef SET_INTERFACE
|
||||
int setinterface(int socket_fd, const char *interface_name);
|
||||
#endif
|
||||
|
||||
int bind_to_address(int socket_fd, const char *address);
|
||||
|
||||
/**
|
||||
* Compare two sockaddrs. Imposes an ordering on the addresses.
|
||||
* Compares address and port.
|
||||
* @param addr1: address 1.
|
||||
* @param addr2: address 2.
|
||||
* @param len: lengths of addr.
|
||||
* @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger.
|
||||
*/
|
||||
int sockaddr_cmp(struct sockaddr_storage *addr1,
|
||||
struct sockaddr_storage *addr2, socklen_t len);
|
||||
|
||||
/**
|
||||
* Compare two sockaddrs. Compares address, not the port.
|
||||
* @param addr1: address 1.
|
||||
* @param addr2: address 2.
|
||||
* @param len: lengths of addr.
|
||||
* @return: 0 if addr1 == addr2. -1 if addr1 is smaller, +1 if larger.
|
||||
*/
|
||||
int sockaddr_cmp_addr(struct sockaddr_storage *addr1,
|
||||
struct sockaddr_storage *addr2, socklen_t len);
|
||||
|
||||
int validate_hostname(const char *hostname, const int hostname_len);
|
||||
|
||||
#endif
|
205
shadowsocksr-libev/src/server/obfs.c
Normal file
205
shadowsocksr-libev/src/server/obfs.c
Normal file
@ -0,0 +1,205 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "obfs.h"
|
||||
|
||||
int rand_bytes(uint8_t *output, int len);
|
||||
#define OBFS_HMAC_SHA1_LEN 10
|
||||
|
||||
#include "obfsutil.c"
|
||||
#include "crc32.c"
|
||||
#include "base64.c"
|
||||
#include "http_simple.c"
|
||||
#include "tls1.2_ticket.c"
|
||||
#include "verify.c"
|
||||
#include "auth.c"
|
||||
|
||||
void * init_data() {
|
||||
return malloc(1);
|
||||
}
|
||||
|
||||
obfs * new_obfs() {
|
||||
obfs * self = (obfs*)malloc(sizeof(obfs));
|
||||
self->l_data = NULL;
|
||||
return self;
|
||||
}
|
||||
|
||||
void set_server_info(obfs *self, server_info *server) {
|
||||
memmove(&self->server, server, sizeof(server_info));
|
||||
}
|
||||
|
||||
void get_server_info(obfs *self, server_info *server) {
|
||||
memmove(server, &self->server, sizeof(server_info));
|
||||
}
|
||||
|
||||
void dispose_obfs(obfs *self) {
|
||||
free(self);
|
||||
}
|
||||
|
||||
obfs_class * new_obfs_class(char *plugin_name)
|
||||
{
|
||||
if (plugin_name == NULL)
|
||||
return NULL;
|
||||
if (strcmp(plugin_name, "origin") == 0)
|
||||
return NULL;
|
||||
if (strcmp(plugin_name, "plain") == 0)
|
||||
return NULL;
|
||||
init_crc32_table();
|
||||
init_shift128plus();
|
||||
if (strcmp(plugin_name, "http_simple") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = init_data;
|
||||
plugin->new_obfs = http_simple_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = http_simple_dispose;
|
||||
|
||||
plugin->client_encode = http_simple_client_encode;
|
||||
plugin->client_decode = http_simple_client_decode;
|
||||
|
||||
plugin->server_encode = http_simple_server_encode;
|
||||
plugin->server_decode = http_simple_server_decode;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "http_post") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = init_data;
|
||||
plugin->new_obfs = http_simple_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = http_simple_dispose;
|
||||
|
||||
plugin->client_encode = http_post_client_encode;
|
||||
plugin->client_decode = http_simple_client_decode;
|
||||
|
||||
plugin->server_encode = http_simple_server_encode;
|
||||
plugin->server_decode = http_simple_server_decode;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "tls1.2_ticket_auth") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = tls12_ticket_auth_init_data;
|
||||
plugin->new_obfs = tls12_ticket_auth_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = tls12_ticket_auth_dispose;
|
||||
|
||||
plugin->client_encode = tls12_ticket_auth_client_encode;
|
||||
plugin->client_decode = tls12_ticket_auth_client_decode;
|
||||
|
||||
plugin->server_encode = tls12_ticket_auth_server_encode;
|
||||
plugin->server_decode = tls12_ticket_auth_server_decode;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "verify_simple") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = init_data;
|
||||
plugin->new_obfs = verify_simple_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = verify_simple_dispose;
|
||||
|
||||
plugin->client_pre_encrypt = verify_simple_client_pre_encrypt;
|
||||
plugin->client_post_decrypt = verify_simple_client_post_decrypt;
|
||||
plugin->client_udp_pre_encrypt = NULL;
|
||||
plugin->client_udp_post_decrypt = NULL;
|
||||
|
||||
plugin->server_pre_encrypt = verify_simple_server_pre_encrypt;
|
||||
plugin->server_post_decrypt = verify_simple_server_post_decrypt;
|
||||
plugin->server_udp_pre_encrypt = NULL;
|
||||
plugin->server_udp_post_decrypt = NULL;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "auth_simple") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = auth_simple_init_data;
|
||||
plugin->new_obfs = auth_simple_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = auth_simple_dispose;
|
||||
|
||||
plugin->client_pre_encrypt = auth_simple_client_pre_encrypt;
|
||||
plugin->client_post_decrypt = auth_simple_client_post_decrypt;
|
||||
plugin->client_udp_pre_encrypt = NULL;
|
||||
plugin->client_udp_post_decrypt = NULL;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "auth_sha1") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = auth_simple_init_data;
|
||||
plugin->new_obfs = auth_simple_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = auth_simple_dispose;
|
||||
|
||||
plugin->client_pre_encrypt = auth_sha1_client_pre_encrypt;
|
||||
plugin->client_post_decrypt = auth_sha1_client_post_decrypt;
|
||||
plugin->client_udp_pre_encrypt = NULL;
|
||||
plugin->client_udp_post_decrypt = NULL;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "auth_sha1_v2") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = auth_simple_init_data;
|
||||
plugin->new_obfs = auth_simple_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = auth_simple_dispose;
|
||||
|
||||
plugin->client_pre_encrypt = auth_sha1_v2_client_pre_encrypt;
|
||||
plugin->client_post_decrypt = auth_sha1_v2_client_post_decrypt;
|
||||
plugin->client_udp_pre_encrypt = NULL;
|
||||
plugin->client_udp_post_decrypt = NULL;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "auth_sha1_v4") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = auth_simple_init_data;
|
||||
plugin->new_obfs = auth_simple_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = auth_simple_dispose;
|
||||
|
||||
plugin->client_pre_encrypt = auth_sha1_v4_client_pre_encrypt;
|
||||
plugin->client_post_decrypt = auth_sha1_v4_client_post_decrypt;
|
||||
plugin->client_udp_pre_encrypt = NULL;
|
||||
plugin->client_udp_post_decrypt = NULL;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "auth_aes128_md5") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = auth_simple_init_data;
|
||||
plugin->new_obfs = auth_aes128_md5_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = auth_simple_dispose;
|
||||
|
||||
plugin->client_pre_encrypt = auth_aes128_sha1_client_pre_encrypt;
|
||||
plugin->client_post_decrypt = auth_aes128_sha1_client_post_decrypt;
|
||||
plugin->client_udp_pre_encrypt = auth_aes128_sha1_client_udp_pre_encrypt;
|
||||
plugin->client_udp_post_decrypt = auth_aes128_sha1_client_udp_post_decrypt;
|
||||
|
||||
return plugin;
|
||||
} else if (strcmp(plugin_name, "auth_aes128_sha1") == 0) {
|
||||
obfs_class * plugin = (obfs_class*)malloc(sizeof(obfs));
|
||||
plugin->init_data = auth_simple_init_data;
|
||||
plugin->new_obfs = auth_aes128_sha1_new_obfs;
|
||||
plugin->get_server_info = get_server_info;
|
||||
plugin->set_server_info = set_server_info;
|
||||
plugin->dispose = auth_simple_dispose;
|
||||
|
||||
plugin->client_pre_encrypt = auth_aes128_sha1_client_pre_encrypt;
|
||||
plugin->client_post_decrypt = auth_aes128_sha1_client_post_decrypt;
|
||||
plugin->client_udp_pre_encrypt = auth_aes128_sha1_client_udp_pre_encrypt;
|
||||
plugin->client_udp_post_decrypt = auth_aes128_sha1_client_udp_post_decrypt;
|
||||
|
||||
return plugin;
|
||||
}
|
||||
LOGE("Load obfs '%s' failed", plugin_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void free_obfs_class(obfs_class *plugin) {
|
||||
free(plugin);
|
||||
}
|
100
shadowsocksr-libev/src/server/obfs.h
Normal file
100
shadowsocksr-libev/src/server/obfs.h
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* obfs.h - Define shadowsocksR server's buffers and callbacks
|
||||
*
|
||||
* Copyright (C) 2015 - 2016, Break Wa11 <mmgac001@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _OBFS_H
|
||||
#define _OBFS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef struct server_info {
|
||||
char host[64];
|
||||
uint16_t port;
|
||||
char *param;
|
||||
void *g_data;
|
||||
uint8_t *iv;
|
||||
size_t iv_len;
|
||||
uint8_t *recv_iv;
|
||||
size_t recv_iv_len;
|
||||
uint8_t *key;
|
||||
size_t key_len;
|
||||
int head_len;
|
||||
size_t tcp_mss;
|
||||
}server_info;
|
||||
|
||||
typedef struct obfs {
|
||||
server_info server;
|
||||
void *l_data;
|
||||
}obfs;
|
||||
|
||||
typedef struct obfs_class {
|
||||
void * (*init_data)();
|
||||
obfs * (*new_obfs)();
|
||||
void (*get_server_info)(obfs *self, server_info *server);
|
||||
void (*set_server_info)(obfs *self, server_info *server);
|
||||
void (*dispose)(obfs *self);
|
||||
|
||||
int (*client_pre_encrypt)(obfs *self,
|
||||
char **pplaindata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*client_encode)(obfs *self,
|
||||
char **pencryptdata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*client_decode)(obfs *self,
|
||||
char **pencryptdata,
|
||||
int datalength,
|
||||
size_t* capacity,
|
||||
int *needsendback);
|
||||
int (*client_post_decrypt)(obfs *self,
|
||||
char **pplaindata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*client_udp_pre_encrypt)(obfs *self,
|
||||
char **pplaindata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*client_udp_post_decrypt)(obfs *self,
|
||||
char **pplaindata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*server_pre_encrypt)(obfs *self,
|
||||
char **pplaindata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*server_post_decrypt)(obfs *self,
|
||||
char **pplaindata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*server_udp_pre_encrypt)(obfs *self,
|
||||
char **pplaindata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*server_udp_post_decrypt)(obfs *self,
|
||||
char **pplaindata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*server_encode)(obfs *self,
|
||||
char **pencryptdata,
|
||||
int datalength,
|
||||
size_t* capacity);
|
||||
int (*server_decode)(obfs *self,
|
||||
char **pencryptdata,
|
||||
int datalength,
|
||||
size_t* capacity,
|
||||
int *needsendback);
|
||||
}obfs_class;
|
||||
|
||||
obfs_class * new_obfs_class(char *plugin_name);
|
||||
void free_obfs_class(obfs_class *plugin);
|
||||
|
||||
void set_server_info(obfs *self, server_info *server);
|
||||
void get_server_info(obfs *self, server_info *server);
|
||||
obfs * new_obfs();
|
||||
void dispose_obfs(obfs *self);
|
||||
|
||||
#endif // _OBFS_H
|
36
shadowsocksr-libev/src/server/obfsutil.c
Normal file
36
shadowsocksr-libev/src/server/obfsutil.c
Normal file
@ -0,0 +1,36 @@
|
||||
int get_head_size(char *plaindata, int size, int def_size) {
|
||||
if (plaindata == NULL || size < 2)
|
||||
return def_size;
|
||||
int head_type = plaindata[0] & 0x7;
|
||||
if (head_type == 1)
|
||||
return 7;
|
||||
if (head_type == 4)
|
||||
return 19;
|
||||
if (head_type == 3)
|
||||
return 4 + plaindata[1];
|
||||
return def_size;
|
||||
}
|
||||
|
||||
static int shift128plus_init_flag = 0;
|
||||
static uint64_t shift128plus_s[2] = {0x10000000, 0xFFFFFFFF};
|
||||
|
||||
void init_shift128plus(void) {
|
||||
if (shift128plus_init_flag == 0) {
|
||||
shift128plus_init_flag = 1;
|
||||
uint32_t seed = time(NULL);
|
||||
shift128plus_s[0] = seed | 0x100000000L;
|
||||
shift128plus_s[1] = ((uint64_t)seed << 32) | 0x1;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t xorshift128plus(void) {
|
||||
uint64_t x = shift128plus_s[0];
|
||||
uint64_t const y = shift128plus_s[1];
|
||||
shift128plus_s[0] = y;
|
||||
x ^= x << 23; // a
|
||||
x ^= x >> 17; // b
|
||||
x ^= y ^ (y >> 26); // c
|
||||
shift128plus_s[1] = x;
|
||||
return x + y;
|
||||
}
|
||||
|
34
shadowsocksr-libev/src/server/protocol.h
Normal file
34
shadowsocksr-libev/src/server/protocol.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef PROTOCOL_H
|
||||
#define PROTOCOL_H
|
||||
|
||||
typedef struct protocol {
|
||||
const int default_port;
|
||||
int(*const parse_packet)(const char *, size_t, char **);
|
||||
} protocol_t;
|
||||
|
||||
#endif
|
444
shadowsocksr-libev/src/server/resolv.c
Normal file
444
shadowsocksr-libev/src/server/resolv.c
Normal file
@ -0,0 +1,444 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <ev.h>
|
||||
#include <udns.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include "win32.h"
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "resolv.h"
|
||||
#include "utils.h"
|
||||
#include "netutils.h"
|
||||
|
||||
/*
|
||||
* Implement DNS resolution interface using libudns
|
||||
*/
|
||||
|
||||
struct ResolvQuery {
|
||||
void (*client_cb)(struct sockaddr *, void *);
|
||||
void (*client_free_cb)(void *);
|
||||
void *client_cb_data;
|
||||
struct dns_query *queries[2];
|
||||
size_t response_count;
|
||||
struct sockaddr **responses;
|
||||
uint16_t port;
|
||||
};
|
||||
|
||||
extern int verbose;
|
||||
|
||||
static struct ev_io resolv_io_watcher;
|
||||
static struct ev_timer resolv_timeout_watcher;
|
||||
static const int MODE_IPV4_ONLY = 0;
|
||||
static const int MODE_IPV6_ONLY = 1;
|
||||
static const int MODE_IPV4_FIRST = 2;
|
||||
static const int MODE_IPV6_FIRST = 3;
|
||||
static int resolv_mode = 0;
|
||||
|
||||
static void resolv_sock_cb(struct ev_loop *, struct ev_io *, int);
|
||||
static void resolv_timeout_cb(struct ev_loop *, struct ev_timer *, int);
|
||||
static void dns_query_v4_cb(struct dns_ctx *, struct dns_rr_a4 *, void *);
|
||||
static void dns_query_v6_cb(struct dns_ctx *, struct dns_rr_a6 *, void *);
|
||||
static void dns_timer_setup_cb(struct dns_ctx *, int, void *);
|
||||
static void process_client_callback(struct ResolvQuery *);
|
||||
static inline int all_queries_are_null(struct ResolvQuery *);
|
||||
static struct sockaddr *choose_ipv4_first(struct ResolvQuery *);
|
||||
static struct sockaddr *choose_ipv6_first(struct ResolvQuery *);
|
||||
static struct sockaddr *choose_any(struct ResolvQuery *);
|
||||
|
||||
int
|
||||
resolv_init(struct ev_loop *loop, char **nameservers, int nameserver_num, int ipv6first)
|
||||
{
|
||||
if (ipv6first)
|
||||
resolv_mode = MODE_IPV6_FIRST;
|
||||
else
|
||||
resolv_mode = MODE_IPV4_FIRST;
|
||||
|
||||
struct dns_ctx *ctx = &dns_defctx;
|
||||
if (nameservers == NULL) {
|
||||
/* Nameservers not specified, use system resolver config */
|
||||
dns_init(ctx, 0);
|
||||
} else {
|
||||
dns_reset(ctx);
|
||||
|
||||
for (int i = 0; i < nameserver_num; i++) {
|
||||
char *server = nameservers[i];
|
||||
dns_add_serv(ctx, server);
|
||||
}
|
||||
}
|
||||
|
||||
int sockfd = dns_open(ctx);
|
||||
if (sockfd < 0) {
|
||||
FATAL("Failed to open DNS resolver socket");
|
||||
}
|
||||
|
||||
if (nameserver_num == 1 && nameservers != NULL) {
|
||||
if (strncmp("127.0.0.1", nameservers[0], 9) == 0
|
||||
|| strncmp("::1", nameservers[0], 3) == 0) {
|
||||
if (verbose) {
|
||||
LOGI("bind UDP resolver to %s", nameservers[0]);
|
||||
}
|
||||
if (bind_to_address(sockfd, nameservers[0]) == -1)
|
||||
ERROR("bind_to_address");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __MINGW32__
|
||||
setnonblocking(sockfd);
|
||||
#else
|
||||
int flags = fcntl(sockfd, F_GETFL, 0);
|
||||
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
|
||||
#endif
|
||||
|
||||
ev_io_init(&resolv_io_watcher, resolv_sock_cb, sockfd, EV_READ);
|
||||
resolv_io_watcher.data = ctx;
|
||||
|
||||
ev_io_start(loop, &resolv_io_watcher);
|
||||
|
||||
ev_timer_init(&resolv_timeout_watcher, resolv_timeout_cb, 0.0, 0.0);
|
||||
resolv_timeout_watcher.data = ctx;
|
||||
|
||||
dns_set_tmcbck(ctx, dns_timer_setup_cb, loop);
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
void
|
||||
resolv_shutdown(struct ev_loop *loop)
|
||||
{
|
||||
struct dns_ctx *ctx = (struct dns_ctx *)resolv_io_watcher.data;
|
||||
|
||||
ev_io_stop(loop, &resolv_io_watcher);
|
||||
|
||||
if (ev_is_active(&resolv_timeout_watcher)) {
|
||||
ev_timer_stop(loop, &resolv_timeout_watcher);
|
||||
}
|
||||
|
||||
dns_close(ctx);
|
||||
}
|
||||
|
||||
struct ResolvQuery *
|
||||
resolv_query(const char *hostname, void (*client_cb)(struct sockaddr *, void *),
|
||||
void (*client_free_cb)(void *), void *client_cb_data,
|
||||
uint16_t port)
|
||||
{
|
||||
struct dns_ctx *ctx = (struct dns_ctx *)resolv_io_watcher.data;
|
||||
|
||||
/*
|
||||
* Wrap udns's call back in our own
|
||||
*/
|
||||
struct ResolvQuery *cb_data = ss_malloc(sizeof(struct ResolvQuery));
|
||||
if (cb_data == NULL) {
|
||||
LOGE("Failed to allocate memory for DNS query callback data.");
|
||||
return NULL;
|
||||
}
|
||||
memset(cb_data, 0, sizeof(struct ResolvQuery));
|
||||
|
||||
cb_data->client_cb = client_cb;
|
||||
cb_data->client_free_cb = client_free_cb;
|
||||
cb_data->client_cb_data = client_cb_data;
|
||||
memset(cb_data->queries, 0, sizeof(cb_data->queries));
|
||||
cb_data->response_count = 0;
|
||||
cb_data->responses = NULL;
|
||||
cb_data->port = port;
|
||||
|
||||
/* Submit A and AAAA queries */
|
||||
if (resolv_mode != MODE_IPV6_ONLY) {
|
||||
cb_data->queries[0] = dns_submit_a4(ctx,
|
||||
hostname, 0,
|
||||
dns_query_v4_cb, cb_data);
|
||||
if (cb_data->queries[0] == NULL) {
|
||||
LOGE("Failed to submit DNS query: %s",
|
||||
dns_strerror(dns_status(ctx)));
|
||||
}
|
||||
}
|
||||
|
||||
if (resolv_mode != MODE_IPV4_ONLY) {
|
||||
cb_data->queries[1] = dns_submit_a6(ctx,
|
||||
hostname, 0,
|
||||
dns_query_v6_cb, cb_data);
|
||||
if (cb_data->queries[1] == NULL) {
|
||||
LOGE("Failed to submit DNS query: %s",
|
||||
dns_strerror(dns_status(ctx)));
|
||||
}
|
||||
}
|
||||
|
||||
if (all_queries_are_null(cb_data)) {
|
||||
if (cb_data->client_free_cb != NULL) {
|
||||
cb_data->client_free_cb(cb_data->client_cb_data);
|
||||
}
|
||||
ss_free(cb_data);
|
||||
}
|
||||
|
||||
return cb_data;
|
||||
}
|
||||
|
||||
void
|
||||
resolv_cancel(struct ResolvQuery *query_handle)
|
||||
{
|
||||
struct ResolvQuery *cb_data = (struct ResolvQuery *)query_handle;
|
||||
struct dns_ctx *ctx = (struct dns_ctx *)resolv_io_watcher.data;
|
||||
|
||||
for (int i = 0; i < sizeof(cb_data->queries) / sizeof(cb_data->queries[0]);
|
||||
i++)
|
||||
if (cb_data->queries[i] != NULL) {
|
||||
dns_cancel(ctx, cb_data->queries[i]);
|
||||
ss_free(cb_data->queries[i]);
|
||||
}
|
||||
|
||||
if (cb_data->client_free_cb != NULL) {
|
||||
cb_data->client_free_cb(cb_data->client_cb_data);
|
||||
}
|
||||
|
||||
ss_free(cb_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* DNS UDP socket activity callback
|
||||
*/
|
||||
static void
|
||||
resolv_sock_cb(struct ev_loop *loop, struct ev_io *w, int revents)
|
||||
{
|
||||
struct dns_ctx *ctx = (struct dns_ctx *)w->data;
|
||||
|
||||
if (revents & EV_READ) {
|
||||
dns_ioevent(ctx, ev_now(loop));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper for client callback we provide to udns
|
||||
*/
|
||||
static void
|
||||
dns_query_v4_cb(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data)
|
||||
{
|
||||
struct ResolvQuery *cb_data = (struct ResolvQuery *)data;
|
||||
|
||||
if (result == NULL) {
|
||||
if (verbose) {
|
||||
LOGI("IPv4 resolv: %s", dns_strerror(dns_status(ctx)));
|
||||
}
|
||||
} else if (result->dnsa4_nrr > 0) {
|
||||
struct sockaddr **new_responses = ss_realloc(cb_data->responses,
|
||||
(cb_data->response_count +
|
||||
result->dnsa4_nrr) *
|
||||
sizeof(struct sockaddr *));
|
||||
if (new_responses == NULL) {
|
||||
LOGE("Failed to allocate memory for additional DNS responses");
|
||||
} else {
|
||||
cb_data->responses = new_responses;
|
||||
|
||||
for (int i = 0; i < result->dnsa4_nrr; i++) {
|
||||
struct sockaddr_in *sa =
|
||||
(struct sockaddr_in *)ss_malloc(sizeof(struct sockaddr_in));
|
||||
sa->sin_family = AF_INET;
|
||||
sa->sin_port = cb_data->port;
|
||||
sa->sin_addr = result->dnsa4_addr[i];
|
||||
|
||||
cb_data->responses[cb_data->response_count] =
|
||||
(struct sockaddr *)sa;
|
||||
if (cb_data->responses[cb_data->response_count] == NULL) {
|
||||
LOGE(
|
||||
"Failed to allocate memory for DNS query result address");
|
||||
} else {
|
||||
cb_data->response_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ss_free(result);
|
||||
cb_data->queries[0] = NULL; /* mark A query as being completed */
|
||||
|
||||
/* Once all queries have completed, call client callback */
|
||||
if (all_queries_are_null(cb_data)) {
|
||||
return process_client_callback(cb_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dns_query_v6_cb(struct dns_ctx *ctx, struct dns_rr_a6 *result, void *data)
|
||||
{
|
||||
struct ResolvQuery *cb_data = (struct ResolvQuery *)data;
|
||||
|
||||
if (result == NULL) {
|
||||
if (verbose) {
|
||||
LOGI("IPv6 resolv: %s", dns_strerror(dns_status(ctx)));
|
||||
}
|
||||
} else if (result->dnsa6_nrr > 0) {
|
||||
struct sockaddr **new_responses = ss_realloc(cb_data->responses,
|
||||
(cb_data->response_count +
|
||||
result->dnsa6_nrr) *
|
||||
sizeof(struct sockaddr *));
|
||||
if (new_responses == NULL) {
|
||||
LOGE("Failed to allocate memory for additional DNS responses");
|
||||
} else {
|
||||
cb_data->responses = new_responses;
|
||||
|
||||
for (int i = 0; i < result->dnsa6_nrr; i++) {
|
||||
struct sockaddr_in6 *sa =
|
||||
(struct sockaddr_in6 *)ss_malloc(sizeof(struct sockaddr_in6));
|
||||
sa->sin6_family = AF_INET6;
|
||||
sa->sin6_port = cb_data->port;
|
||||
sa->sin6_addr = result->dnsa6_addr[i];
|
||||
|
||||
cb_data->responses[cb_data->response_count] =
|
||||
(struct sockaddr *)sa;
|
||||
if (cb_data->responses[cb_data->response_count] == NULL) {
|
||||
LOGE(
|
||||
"Failed to allocate memory for DNS query result address");
|
||||
} else {
|
||||
cb_data->response_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ss_free(result);
|
||||
cb_data->queries[1] = NULL; /* mark AAAA query as being completed */
|
||||
|
||||
/* Once all queries have completed, call client callback */
|
||||
if (all_queries_are_null(cb_data)) {
|
||||
return process_client_callback(cb_data);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called once all queries have been completed
|
||||
*/
|
||||
static void
|
||||
process_client_callback(struct ResolvQuery *cb_data)
|
||||
{
|
||||
struct sockaddr *best_address = NULL;
|
||||
|
||||
if (resolv_mode == MODE_IPV4_FIRST) {
|
||||
best_address = choose_ipv4_first(cb_data);
|
||||
} else if (resolv_mode == MODE_IPV6_FIRST) {
|
||||
best_address = choose_ipv6_first(cb_data);
|
||||
} else {
|
||||
best_address = choose_any(cb_data);
|
||||
}
|
||||
|
||||
cb_data->client_cb(best_address, cb_data->client_cb_data);
|
||||
|
||||
for (int i = 0; i < cb_data->response_count; i++)
|
||||
ss_free(cb_data->responses[i]);
|
||||
|
||||
ss_free(cb_data->responses);
|
||||
if (cb_data->client_free_cb != NULL) {
|
||||
cb_data->client_free_cb(cb_data->client_cb_data);
|
||||
}
|
||||
ss_free(cb_data);
|
||||
}
|
||||
|
||||
static struct sockaddr *
|
||||
choose_ipv4_first(struct ResolvQuery *cb_data)
|
||||
{
|
||||
for (int i = 0; i < cb_data->response_count; i++)
|
||||
if (cb_data->responses[i]->sa_family == AF_INET) {
|
||||
return cb_data->responses[i];
|
||||
}
|
||||
|
||||
return choose_any(cb_data);
|
||||
}
|
||||
|
||||
static struct sockaddr *
|
||||
choose_ipv6_first(struct ResolvQuery *cb_data)
|
||||
{
|
||||
for (int i = 0; i < cb_data->response_count; i++)
|
||||
if (cb_data->responses[i]->sa_family == AF_INET6) {
|
||||
return cb_data->responses[i];
|
||||
}
|
||||
|
||||
return choose_any(cb_data);
|
||||
}
|
||||
|
||||
static struct sockaddr *
|
||||
choose_any(struct ResolvQuery *cb_data)
|
||||
{
|
||||
if (cb_data->response_count >= 1) {
|
||||
return cb_data->responses[0];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* DNS timeout callback
|
||||
*/
|
||||
static void
|
||||
resolv_timeout_cb(struct ev_loop *loop, struct ev_timer *w, int revents)
|
||||
{
|
||||
struct dns_ctx *ctx = (struct dns_ctx *)w->data;
|
||||
|
||||
if (revents & EV_TIMER) {
|
||||
dns_timeouts(ctx, 30, ev_now(loop));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback to setup DNS timeout callback
|
||||
*/
|
||||
static void
|
||||
dns_timer_setup_cb(struct dns_ctx *ctx, int timeout, void *data)
|
||||
{
|
||||
struct ev_loop *loop = (struct ev_loop *)data;
|
||||
|
||||
if (ev_is_active(&resolv_timeout_watcher)) {
|
||||
ev_timer_stop(loop, &resolv_timeout_watcher);
|
||||
}
|
||||
|
||||
if (ctx != NULL && timeout >= 0) {
|
||||
ev_timer_set(&resolv_timeout_watcher, timeout, 0.0);
|
||||
ev_timer_start(loop, &resolv_timeout_watcher);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
all_queries_are_null(struct ResolvQuery *cb_data)
|
||||
{
|
||||
int result = 1;
|
||||
|
||||
for (int i = 0; i < sizeof(cb_data->queries) / sizeof(cb_data->queries[0]);
|
||||
i++)
|
||||
result = result && cb_data->queries[i] == NULL;
|
||||
|
||||
return result;
|
||||
}
|
50
shadowsocksr-libev/src/server/resolv.h
Normal file
50
shadowsocksr-libev/src/server/resolv.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef RESOLV_H
|
||||
#define RESOLV_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include "win32.h"
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
struct ResolvQuery;
|
||||
|
||||
int resolv_init(struct ev_loop *, char **, int, int);
|
||||
struct ResolvQuery *resolv_query(const char *, void (*)(struct sockaddr *,
|
||||
void *), void (*)(
|
||||
void *), void *, uint16_t);
|
||||
void resolv_cancel(struct ResolvQuery *);
|
||||
void resolv_shutdown(struct ev_loop *);
|
||||
|
||||
#endif
|
137
shadowsocksr-libev/src/server/rule.c
Normal file
137
shadowsocksr-libev/src/server/rule.c
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* Copyright (c) 2011 Manuel Kasper <mk@neon1.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
extern void ss_error(const char *s);
|
||||
#endif
|
||||
|
||||
#include "rule.h"
|
||||
#include "utils.h"
|
||||
|
||||
static void free_rule(rule_t *);
|
||||
|
||||
rule_t *
|
||||
new_rule()
|
||||
{
|
||||
rule_t *rule;
|
||||
|
||||
rule = calloc(1, sizeof(rule_t));
|
||||
if (rule == NULL) {
|
||||
ERROR("malloc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rule;
|
||||
}
|
||||
|
||||
int
|
||||
accept_rule_arg(rule_t *rule, const char *arg)
|
||||
{
|
||||
if (rule->pattern == NULL) {
|
||||
rule->pattern = strdup(arg);
|
||||
if (rule->pattern == NULL) {
|
||||
ERROR("strdup failed");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
LOGE("Unexpected table rule argument: %s", arg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
add_rule(struct cork_dllist *rules, rule_t *rule)
|
||||
{
|
||||
cork_dllist_add(rules, &rule->entries);
|
||||
}
|
||||
|
||||
int
|
||||
init_rule(rule_t *rule)
|
||||
{
|
||||
if (rule->pattern_re == NULL) {
|
||||
const char *reerr;
|
||||
int reerroffset;
|
||||
|
||||
rule->pattern_re =
|
||||
pcre_compile(rule->pattern, 0, &reerr, &reerroffset, NULL);
|
||||
if (rule->pattern_re == NULL) {
|
||||
LOGE("Regex compilation of \"%s\" failed: %s, offset %d",
|
||||
rule->pattern, reerr, reerroffset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
rule_t *
|
||||
lookup_rule(const struct cork_dllist *rules, const char *name, size_t name_len)
|
||||
{
|
||||
struct cork_dllist_item *curr, *next;
|
||||
|
||||
if (name == NULL) {
|
||||
name = "";
|
||||
name_len = 0;
|
||||
}
|
||||
|
||||
cork_dllist_foreach_void(rules, curr, next) {
|
||||
rule_t *rule = cork_container_of(curr, rule_t, entries);
|
||||
if (pcre_exec(rule->pattern_re, NULL,
|
||||
name, name_len, 0, 0, NULL, 0) >= 0)
|
||||
return rule;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
remove_rule(rule_t *rule)
|
||||
{
|
||||
cork_dllist_remove(&rule->entries);
|
||||
free_rule(rule);
|
||||
}
|
||||
|
||||
static void
|
||||
free_rule(rule_t *rule)
|
||||
{
|
||||
if (rule == NULL)
|
||||
return;
|
||||
|
||||
ss_free(rule->pattern);
|
||||
if (rule->pattern_re != NULL)
|
||||
pcre_free(rule->pattern_re);
|
||||
ss_free(rule);
|
||||
}
|
58
shadowsocksr-libev/src/server/rule.h
Normal file
58
shadowsocksr-libev/src/server/rule.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* Copyright (c) 2011 Manuel Kasper <mk@neon1.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef RULE_H
|
||||
#define RULE_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <libcork/ds.h>
|
||||
|
||||
#ifdef HAVE_PCRE_H
|
||||
#include <pcre.h>
|
||||
#elif HAVE_PCRE_PCRE_H
|
||||
#include <pcre/pcre.h>
|
||||
#endif
|
||||
|
||||
typedef struct rule {
|
||||
char *pattern;
|
||||
|
||||
/* Runtime fields */
|
||||
pcre *pattern_re;
|
||||
|
||||
struct cork_dllist_item entries;
|
||||
} rule_t;
|
||||
|
||||
void add_rule(struct cork_dllist *, rule_t *);
|
||||
int init_rule(rule_t *);
|
||||
rule_t *lookup_rule(const struct cork_dllist *, const char *, size_t);
|
||||
void remove_rule(rule_t *);
|
||||
rule_t *new_rule();
|
||||
int accept_rule_arg(rule_t *, const char *);
|
||||
|
||||
#endif
|
2209
shadowsocksr-libev/src/server/server.c
Normal file
2209
shadowsocksr-libev/src/server/server.c
Normal file
File diff suppressed because it is too large
Load Diff
115
shadowsocksr-libev/src/server/server.h
Normal file
115
shadowsocksr-libev/src/server/server.h
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* server.h - Define shadowsocks server's buffers and callbacks
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* This file is part of the shadowsocks-libev.
|
||||
*
|
||||
* shadowsocks-libev is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* shadowsocks-libev is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with shadowsocks-libev; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SERVER_H
|
||||
#define _SERVER_H
|
||||
|
||||
#include <ev.h>
|
||||
#include <time.h>
|
||||
#include <libcork/ds.h>
|
||||
|
||||
#include "encrypt.h"
|
||||
#include "jconf.h"
|
||||
#include "resolv.h"
|
||||
#include "obfs.h"
|
||||
#include "protocol.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
typedef struct listen_ctx {
|
||||
ev_io io;
|
||||
int fd;
|
||||
int timeout;
|
||||
int method;
|
||||
char *iface;
|
||||
struct ev_loop *loop;
|
||||
|
||||
// SSR
|
||||
char *protocol_name;
|
||||
char *protocol_param;
|
||||
char *obfs_name;
|
||||
char *obfs_param;
|
||||
void **list_protocol_global;
|
||||
void **list_obfs_global;
|
||||
} listen_ctx_t;
|
||||
|
||||
typedef struct server_ctx {
|
||||
ev_io io;
|
||||
ev_timer watcher;
|
||||
int connected;
|
||||
struct server *server;
|
||||
} server_ctx_t;
|
||||
|
||||
typedef struct server {
|
||||
int fd;
|
||||
int stage;
|
||||
buffer_t *buf;
|
||||
ssize_t buf_capacity;
|
||||
buffer_t *header_buf;
|
||||
|
||||
int auth;
|
||||
struct chunk *chunk;
|
||||
|
||||
struct enc_ctx *e_ctx;
|
||||
struct enc_ctx *d_ctx;
|
||||
struct server_ctx *recv_ctx;
|
||||
struct server_ctx *send_ctx;
|
||||
struct listen_ctx *listen_ctx;
|
||||
struct remote *remote;
|
||||
|
||||
struct ResolvQuery *query;
|
||||
|
||||
struct cork_dllist_item entries;
|
||||
|
||||
// SSR
|
||||
obfs *protocol;
|
||||
obfs *obfs;
|
||||
obfs_class *protocol_plugin;
|
||||
obfs_class *obfs_plugin;
|
||||
int obfs_compatible_state;
|
||||
int protocol_compatible_state;
|
||||
} server_t;
|
||||
|
||||
typedef struct query {
|
||||
server_t *server;
|
||||
char hostname[257];
|
||||
} query_t;
|
||||
|
||||
typedef struct remote_ctx {
|
||||
ev_io io;
|
||||
int connected;
|
||||
struct remote *remote;
|
||||
} remote_ctx_t;
|
||||
|
||||
typedef struct remote {
|
||||
int fd;
|
||||
buffer_t *buf;
|
||||
ssize_t buf_capacity;
|
||||
struct remote_ctx *recv_ctx;
|
||||
struct remote_ctx *send_ctx;
|
||||
struct server *server;
|
||||
|
||||
// SSR
|
||||
int remote_index;
|
||||
} remote_t;
|
||||
|
||||
#endif // _SERVER_H
|
263
shadowsocksr-libev/src/server/tls.c
Normal file
263
shadowsocksr-libev/src/server/tls.c
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* This is a minimal TLS implementation intended only to parse the server name
|
||||
* extension. This was created based primarily on Wireshark dissection of a
|
||||
* TLS handshake and RFC4366.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* malloc() */
|
||||
#include <string.h> /* strncpy() */
|
||||
|
||||
#ifndef __MINGW32__
|
||||
#include <sys/socket.h>
|
||||
#else
|
||||
#include <win32.h>
|
||||
#endif
|
||||
|
||||
#include "tls.h"
|
||||
#include "protocol.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define SERVER_NAME_LEN 256
|
||||
#define TLS_HEADER_LEN 5
|
||||
#define TLS_HANDSHAKE_CONTENT_TYPE 0x16
|
||||
#define TLS_HANDSHAKE_TYPE_CLIENT_HELLO 0x01
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
|
||||
#endif
|
||||
|
||||
extern int verbose;
|
||||
|
||||
static int parse_tls_header(const char *, size_t, char **);
|
||||
static int parse_extensions(const char *, size_t, char **);
|
||||
static int parse_server_name_extension(const char *, size_t, char **);
|
||||
|
||||
static const protocol_t tls_protocol_st = {
|
||||
.default_port = 443,
|
||||
.parse_packet = &parse_tls_header,
|
||||
};
|
||||
const protocol_t *const tls_protocol = &tls_protocol_st;
|
||||
|
||||
/* Parse a TLS packet for the Server Name Indication extension in the client
|
||||
* hello handshake, returning the first servername found (pointer to static
|
||||
* array)
|
||||
*
|
||||
* Returns:
|
||||
* >=0 - length of the hostname and updates *hostname
|
||||
* caller is responsible for freeing *hostname
|
||||
* -1 - Incomplete request
|
||||
* -2 - No Host header included in this request
|
||||
* -3 - Invalid hostname pointer
|
||||
* -4 - malloc failure
|
||||
* < -4 - Invalid TLS client hello
|
||||
*/
|
||||
static int
|
||||
parse_tls_header(const char *data, size_t data_len, char **hostname)
|
||||
{
|
||||
char tls_content_type;
|
||||
char tls_version_major;
|
||||
char tls_version_minor;
|
||||
size_t pos = TLS_HEADER_LEN;
|
||||
size_t len;
|
||||
|
||||
if (hostname == NULL)
|
||||
return -3;
|
||||
|
||||
/* Check that our TCP payload is at least large enough for a TLS header */
|
||||
if (data_len < TLS_HEADER_LEN)
|
||||
return -1;
|
||||
|
||||
/* SSL 2.0 compatible Client Hello
|
||||
*
|
||||
* High bit of first byte (length) and content type is Client Hello
|
||||
*
|
||||
* See RFC5246 Appendix E.2
|
||||
*/
|
||||
if (data[0] & 0x80 && data[2] == 1) {
|
||||
if (verbose)
|
||||
LOGI("Received SSL 2.0 Client Hello which can not support SNI.");
|
||||
return -2;
|
||||
}
|
||||
|
||||
tls_content_type = data[0];
|
||||
if (tls_content_type != TLS_HANDSHAKE_CONTENT_TYPE) {
|
||||
if (verbose)
|
||||
LOGI("Request did not begin with TLS handshake.");
|
||||
return -5;
|
||||
}
|
||||
|
||||
tls_version_major = data[1];
|
||||
tls_version_minor = data[2];
|
||||
if (tls_version_major < 3) {
|
||||
if (verbose)
|
||||
LOGI("Received SSL %d.%d handshake which can not support SNI.",
|
||||
tls_version_major, tls_version_minor);
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* TLS record length */
|
||||
len = ((unsigned char)data[3] << 8) +
|
||||
(unsigned char)data[4] + TLS_HEADER_LEN;
|
||||
data_len = MIN(data_len, len);
|
||||
|
||||
/* Check we received entire TLS record length */
|
||||
if (data_len < len)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Handshake
|
||||
*/
|
||||
if (pos + 1 > data_len) {
|
||||
return -5;
|
||||
}
|
||||
if (data[pos] != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) {
|
||||
if (verbose)
|
||||
LOGI("Not a client hello");
|
||||
|
||||
return -5;
|
||||
}
|
||||
|
||||
/* Skip past fixed length records:
|
||||
* 1 Handshake Type
|
||||
* 3 Length
|
||||
* 2 Version (again)
|
||||
* 32 Random
|
||||
* to Session ID Length
|
||||
*/
|
||||
pos += 38;
|
||||
|
||||
/* Session ID */
|
||||
if (pos + 1 > data_len)
|
||||
return -5;
|
||||
len = (unsigned char)data[pos];
|
||||
pos += 1 + len;
|
||||
|
||||
/* Cipher Suites */
|
||||
if (pos + 2 > data_len)
|
||||
return -5;
|
||||
len = ((unsigned char)data[pos] << 8) + (unsigned char)data[pos + 1];
|
||||
pos += 2 + len;
|
||||
|
||||
/* Compression Methods */
|
||||
if (pos + 1 > data_len)
|
||||
return -5;
|
||||
len = (unsigned char)data[pos];
|
||||
pos += 1 + len;
|
||||
|
||||
if (pos == data_len && tls_version_major == 3 && tls_version_minor == 0) {
|
||||
if (verbose)
|
||||
LOGI("Received SSL 3.0 handshake without extensions");
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Extensions */
|
||||
if (pos + 2 > data_len)
|
||||
return -5;
|
||||
len = ((unsigned char)data[pos] << 8) + (unsigned char)data[pos + 1];
|
||||
pos += 2;
|
||||
|
||||
if (pos + len > data_len)
|
||||
return -5;
|
||||
return parse_extensions(data + pos, len, hostname);
|
||||
}
|
||||
|
||||
static int
|
||||
parse_extensions(const char *data, size_t data_len, char **hostname)
|
||||
{
|
||||
size_t pos = 0;
|
||||
size_t len;
|
||||
|
||||
/* Parse each 4 bytes for the extension header */
|
||||
while (pos + 4 <= data_len) {
|
||||
/* Extension Length */
|
||||
len = ((unsigned char)data[pos + 2] << 8) +
|
||||
(unsigned char)data[pos + 3];
|
||||
|
||||
/* Check if it's a server name extension */
|
||||
if (data[pos] == 0x00 && data[pos + 1] == 0x00) {
|
||||
/* There can be only one extension of each type, so we break
|
||||
* our state and move p to beinnging of the extension here */
|
||||
if (pos + 4 + len > data_len)
|
||||
return -5;
|
||||
return parse_server_name_extension(data + pos + 4, len, hostname);
|
||||
}
|
||||
pos += 4 + len; /* Advance to the next extension header */
|
||||
}
|
||||
/* Check we ended where we expected to */
|
||||
if (pos != data_len)
|
||||
return -5;
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_server_name_extension(const char *data, size_t data_len,
|
||||
char **hostname)
|
||||
{
|
||||
size_t pos = 2; /* skip server name list length */
|
||||
size_t len;
|
||||
|
||||
while (pos + 3 < data_len) {
|
||||
len = ((unsigned char)data[pos + 1] << 8) +
|
||||
(unsigned char)data[pos + 2];
|
||||
|
||||
if (pos + 3 + len > data_len)
|
||||
return -5;
|
||||
|
||||
switch (data[pos]) { /* name type */
|
||||
case 0x00: /* host_name */
|
||||
*hostname = malloc(len + 1);
|
||||
if (*hostname == NULL) {
|
||||
ERROR("malloc() failure");
|
||||
return -4;
|
||||
}
|
||||
|
||||
strncpy(*hostname, data + pos + 3, len);
|
||||
|
||||
(*hostname)[len] = '\0';
|
||||
|
||||
return len;
|
||||
default:
|
||||
if (verbose)
|
||||
LOGI("Unknown server name extension name type: %d",
|
||||
data[pos]);
|
||||
}
|
||||
pos += 3 + len;
|
||||
}
|
||||
/* Check we ended where we expected to */
|
||||
if (pos != data_len)
|
||||
return -5;
|
||||
|
||||
return -2;
|
||||
}
|
33
shadowsocksr-libev/src/server/tls.h
Normal file
33
shadowsocksr-libev/src/server/tls.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef TLS_H
|
||||
#define TLS_H
|
||||
|
||||
#include "protocol.h"
|
||||
|
||||
const protocol_t *const tls_protocol;
|
||||
|
||||
#endif
|
609
shadowsocksr-libev/src/server/tls1.2_ticket.c
Normal file
609
shadowsocksr-libev/src/server/tls1.2_ticket.c
Normal file
@ -0,0 +1,609 @@
|
||||
|
||||
#include "tls1.2_ticket.h"
|
||||
#include "list.c"
|
||||
|
||||
typedef struct tls12_ticket_auth_global_data {
|
||||
uint8_t local_client_id[32];
|
||||
List client_data;
|
||||
time_t startup_time;
|
||||
}tls12_ticket_auth_global_data;
|
||||
|
||||
typedef struct tls12_ticket_auth_local_data {
|
||||
int handshake_status;
|
||||
char *send_buffer;
|
||||
int send_buffer_size;
|
||||
char *recv_buffer;
|
||||
int recv_buffer_size;
|
||||
}tls12_ticket_auth_local_data;
|
||||
|
||||
void tls12_ticket_auth_local_data_init(tls12_ticket_auth_local_data* local) {
|
||||
local->handshake_status = 0;
|
||||
local->send_buffer = malloc(0);
|
||||
local->send_buffer_size = 0;
|
||||
local->recv_buffer = malloc(0);
|
||||
local->recv_buffer_size = 0;
|
||||
}
|
||||
|
||||
void * tls12_ticket_auth_init_data() {
|
||||
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)malloc(sizeof(tls12_ticket_auth_global_data));
|
||||
rand_bytes(global->local_client_id, 32);
|
||||
global->client_data = list_init(22);
|
||||
global->startup_time = time(NULL);
|
||||
return global;
|
||||
}
|
||||
|
||||
obfs * tls12_ticket_auth_new_obfs() {
|
||||
obfs * self = new_obfs();
|
||||
self->l_data = malloc(sizeof(tls12_ticket_auth_local_data));
|
||||
tls12_ticket_auth_local_data_init((tls12_ticket_auth_local_data*)self->l_data);
|
||||
return self;
|
||||
}
|
||||
|
||||
void tls12_ticket_auth_dispose(obfs *self) {
|
||||
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
|
||||
if (local->send_buffer != NULL) {
|
||||
free(local->send_buffer);
|
||||
local->send_buffer = NULL;
|
||||
}
|
||||
if (local->recv_buffer != NULL) {
|
||||
free(local->recv_buffer);
|
||||
local->recv_buffer = NULL;
|
||||
}
|
||||
free(local);
|
||||
dispose_obfs(self);
|
||||
}
|
||||
|
||||
int tls12_ticket_pack_auth_data(tls12_ticket_auth_global_data *global, server_info *server, char *outdata) {
|
||||
int out_size = 32;
|
||||
time_t t = time(NULL);
|
||||
outdata[0] = t >> 24;
|
||||
outdata[1] = t >> 16;
|
||||
outdata[2] = t >> 8;
|
||||
outdata[3] = t;
|
||||
rand_bytes((uint8_t*)outdata + 4, 18);
|
||||
|
||||
uint8_t *key = (uint8_t*)malloc(server->key_len + 32);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
memcpy(key, server->key, server->key_len);
|
||||
memcpy(key + server->key_len, global->local_client_id, 32);
|
||||
ss_sha1_hmac_with_key(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, key, server->key_len + 32);
|
||||
free(key);
|
||||
memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
void tls12_ticket_auth_pack_data(char *encryptdata, int datalength, int start, int len, char *out_buffer, int outlength) {
|
||||
out_buffer[outlength] = 0x17;
|
||||
out_buffer[outlength + 1] = 0x3;
|
||||
out_buffer[outlength + 2] = 0x3;
|
||||
out_buffer[outlength + 3] = len >> 8;
|
||||
out_buffer[outlength + 4] = len;
|
||||
memcpy(out_buffer + outlength + 5, encryptdata + start, len);
|
||||
}
|
||||
|
||||
int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
|
||||
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data;
|
||||
char * out_buffer = NULL;
|
||||
|
||||
if (local->handshake_status == 8) {
|
||||
if (datalength < 1024) {
|
||||
if (*capacity < datalength + 5) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + 5) * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memmove(encryptdata + 5, encryptdata, datalength);
|
||||
encryptdata[0] = 0x17;
|
||||
encryptdata[1] = 0x3;
|
||||
encryptdata[2] = 0x3;
|
||||
encryptdata[3] = datalength >> 8;
|
||||
encryptdata[4] = datalength;
|
||||
return datalength + 5;
|
||||
} else {
|
||||
out_buffer = (char*)malloc(datalength + 2048);
|
||||
int start = 0;
|
||||
int outlength = 0;
|
||||
int len;
|
||||
while (datalength - start > 2048) {
|
||||
len = xorshift128plus() % 4096 + 100;
|
||||
if (len > datalength - start)
|
||||
len = datalength - start;
|
||||
tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength);
|
||||
outlength += len + 5;
|
||||
start += len;
|
||||
}
|
||||
if (datalength - start > 0) {
|
||||
len = datalength - start;
|
||||
tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength);
|
||||
outlength += len + 5;
|
||||
}
|
||||
if (*capacity < outlength) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memcpy(encryptdata, out_buffer, outlength);
|
||||
free(out_buffer);
|
||||
return outlength;
|
||||
}
|
||||
}
|
||||
local->send_buffer = (char*)realloc(local->send_buffer, local->send_buffer_size + datalength + 5);
|
||||
memcpy(local->send_buffer + local->send_buffer_size + 5, encryptdata, datalength);
|
||||
local->send_buffer[local->send_buffer_size] = 0x17;
|
||||
local->send_buffer[local->send_buffer_size + 1] = 0x3;
|
||||
local->send_buffer[local->send_buffer_size + 2] = 0x3;
|
||||
local->send_buffer[local->send_buffer_size + 3] = datalength >> 8;
|
||||
local->send_buffer[local->send_buffer_size + 4] = datalength;
|
||||
local->send_buffer_size += datalength + 5;
|
||||
|
||||
if (local->handshake_status == 0) {
|
||||
#define CSTR_DECL(name, len, str) const char* name = str; const int len = sizeof(str) - 1;
|
||||
CSTR_DECL(tls_data0, tls_data0_len, "\x00\x1c\xc0\x2b\xc0\x2f\xcc\xa9\xcc\xa8\xcc\x14\xcc\x13\xc0\x0a\xc0\x14\xc0\x09\xc0\x13\x00\x9c\x00\x35\x00\x2f\x00\x0a\x01\x00"
|
||||
);
|
||||
CSTR_DECL(tls_data1, tls_data1_len, "\xff\x01\x00\x01\x00"
|
||||
);
|
||||
CSTR_DECL(tls_data2, tls_data2_len, "\x00\x17\x00\x00\x00\x23\x00\xd0");
|
||||
CSTR_DECL(tls_data3, tls_data3_len, "\x00\x0d\x00\x16\x00\x14\x06\x01\x06\x03\x05\x01\x05\x03\x04\x01\x04\x03\x03\x01\x03\x03\x02\x01\x02\x03\x00\x05\x00\x05\x01\x00\x00\x00\x00\x00\x12\x00\x00\x75\x50\x00\x00\x00\x0b\x00\x02\x01\x00\x00\x0a\x00\x06\x00\x04\x00\x17\x00\x18"
|
||||
//"00150066000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" // padding
|
||||
);
|
||||
uint8_t tls_data[2048];
|
||||
int tls_data_len = 0;
|
||||
memcpy(tls_data, tls_data1, tls_data1_len);
|
||||
tls_data_len += tls_data1_len;
|
||||
|
||||
char hosts[1024];
|
||||
char * phost[128];
|
||||
int host_num = 0;
|
||||
int pos;
|
||||
|
||||
char sni[256] = {0};
|
||||
if (self->server.param && strlen(self->server.param) == 0)
|
||||
self->server.param = NULL;
|
||||
strncpy(hosts, self->server.param ? self->server.param : self->server.host, sizeof hosts);
|
||||
phost[host_num++] = hosts;
|
||||
for (pos = 0; hosts[pos]; ++pos) {
|
||||
if (hosts[pos] == ',') {
|
||||
phost[host_num++] = &hosts[pos + 1];
|
||||
}
|
||||
}
|
||||
host_num = xorshift128plus() % host_num;
|
||||
|
||||
sprintf(sni, "%s", phost[host_num]);
|
||||
int sni_len = strlen(sni);
|
||||
if (sni_len > 0 && sni[sni_len - 1] >= '0' && sni[sni_len - 1] <= '9')
|
||||
sni_len = 0;
|
||||
tls_data[tls_data_len] = '\0';
|
||||
tls_data[tls_data_len + 1] = '\0';
|
||||
tls_data[tls_data_len + 2] = (sni_len + 5) >> 8;
|
||||
tls_data[tls_data_len + 3] = (sni_len + 5);
|
||||
tls_data[tls_data_len + 4] = (sni_len + 3) >> 8;
|
||||
tls_data[tls_data_len + 5] = (sni_len + 3);
|
||||
tls_data[tls_data_len + 6] = '\0';
|
||||
tls_data[tls_data_len + 7] = sni_len >> 8;
|
||||
tls_data[tls_data_len + 8] = sni_len;
|
||||
memcpy(tls_data + tls_data_len + 9, sni, sni_len);
|
||||
tls_data_len += 9 + sni_len;
|
||||
memcpy(tls_data + tls_data_len, tls_data2, tls_data2_len);
|
||||
tls_data_len += tls_data2_len;
|
||||
rand_bytes(tls_data + tls_data_len, 208);
|
||||
tls_data_len += 208;
|
||||
memcpy(tls_data + tls_data_len, tls_data3, tls_data3_len);
|
||||
tls_data_len += tls_data3_len;
|
||||
|
||||
datalength = 11 + 32 + 1 + 32 + tls_data0_len + 2 + tls_data_len;
|
||||
out_buffer = (char*)malloc(datalength);
|
||||
char *pdata = out_buffer + datalength - tls_data_len;
|
||||
int len = tls_data_len;
|
||||
memcpy(pdata, tls_data, tls_data_len);
|
||||
pdata[-1] = tls_data_len;
|
||||
pdata[-2] = tls_data_len >> 8;
|
||||
pdata -= 2; len += 2;
|
||||
memcpy(pdata - tls_data0_len, tls_data0, tls_data0_len);
|
||||
pdata -= tls_data0_len; len += tls_data0_len;
|
||||
memcpy(pdata - 32, global->local_client_id, 32);
|
||||
pdata -= 32; len += 32;
|
||||
pdata[-1] = 0x20;
|
||||
pdata -= 1; len += 1;
|
||||
tls12_ticket_pack_auth_data(global, &self->server, pdata - 32);
|
||||
pdata -= 32; len += 32;
|
||||
pdata[-1] = 0x3;
|
||||
pdata[-2] = 0x3; // tls version
|
||||
pdata -= 2; len += 2;
|
||||
pdata[-1] = len;
|
||||
pdata[-2] = len >> 8;
|
||||
pdata[-3] = 0;
|
||||
pdata[-4] = 1;
|
||||
pdata -= 4; len += 4;
|
||||
|
||||
pdata[-1] = len;
|
||||
pdata[-2] = len >> 8;
|
||||
pdata -= 2; len += 2;
|
||||
pdata[-1] = 0x1;
|
||||
pdata[-2] = 0x3; // tls version
|
||||
pdata -= 2; len += 2;
|
||||
pdata[-1] = 0x16; // tls handshake
|
||||
pdata -= 1; len += 1;
|
||||
|
||||
local->handshake_status = 1;
|
||||
} else if (datalength == 0) {
|
||||
datalength = local->send_buffer_size + 43;
|
||||
out_buffer = (char*)malloc(datalength);
|
||||
char *pdata = out_buffer;
|
||||
memcpy(pdata, "\x14\x03\x03\x00\x01\x01", 6);
|
||||
pdata += 6;
|
||||
memcpy(pdata, "\x16\x03\x03\x00\x20", 5);
|
||||
pdata += 5;
|
||||
rand_bytes((uint8_t*)pdata, 22);
|
||||
pdata += 22;
|
||||
|
||||
uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
memcpy(key, self->server.key, self->server.key_len);
|
||||
memcpy(key + self->server.key_len, global->local_client_id, 32);
|
||||
ss_sha1_hmac_with_key(hash, out_buffer, pdata - out_buffer, key, self->server.key_len + 32);
|
||||
free(key);
|
||||
memcpy(pdata, hash, OBFS_HMAC_SHA1_LEN);
|
||||
|
||||
pdata += OBFS_HMAC_SHA1_LEN;
|
||||
memcpy(pdata, local->send_buffer, local->send_buffer_size);
|
||||
free(local->send_buffer);
|
||||
local->send_buffer = NULL;
|
||||
|
||||
local->handshake_status = 8;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if (*capacity < datalength) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = datalength * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memmove(encryptdata, out_buffer, datalength);
|
||||
free(out_buffer);
|
||||
return datalength;
|
||||
}
|
||||
|
||||
int tls12_ticket_auth_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
|
||||
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data;
|
||||
char * out_buffer = NULL;
|
||||
|
||||
if (local->handshake_status == 8) {
|
||||
if (datalength < 1024) {
|
||||
if (*capacity < datalength + 5) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + 5) * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memmove(encryptdata + 5, encryptdata, datalength);
|
||||
encryptdata[0] = 0x17;
|
||||
encryptdata[1] = 0x3;
|
||||
encryptdata[2] = 0x3;
|
||||
encryptdata[3] = datalength >> 8;
|
||||
encryptdata[4] = datalength;
|
||||
return datalength + 5;
|
||||
} else {
|
||||
out_buffer = (char*)malloc(datalength + 2048);
|
||||
int start = 0;
|
||||
int outlength = 0;
|
||||
int len;
|
||||
while (datalength - start > 2048) {
|
||||
len = xorshift128plus() % 4096 + 100;
|
||||
if (len > datalength - start)
|
||||
len = datalength - start;
|
||||
tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength);
|
||||
outlength += len + 5;
|
||||
start += len;
|
||||
}
|
||||
if (datalength - start > 0) {
|
||||
len = datalength - start;
|
||||
tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength);
|
||||
outlength += len + 5;
|
||||
}
|
||||
if (*capacity < outlength) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memcpy(encryptdata, out_buffer, outlength);
|
||||
free(out_buffer);
|
||||
return outlength;
|
||||
}
|
||||
}
|
||||
|
||||
local->handshake_status = 3;
|
||||
|
||||
out_buffer = (char*)malloc(43 + 86);
|
||||
int data_len = 0;
|
||||
char *p_data = out_buffer + 86;
|
||||
|
||||
memcpy(p_data - 10, "\xc0\x2f\x00\x00\x05\xff\x01\x00\x01\x00", 10);
|
||||
p_data -= 10;data_len += 10;
|
||||
|
||||
memcpy(p_data - 32, global->local_client_id, 32);
|
||||
p_data -= 32;data_len += 32;
|
||||
|
||||
p_data[-1] = 0x20;
|
||||
p_data -= 1;data_len += 1;
|
||||
|
||||
tls12_ticket_pack_auth_data(global, &self->server, p_data - 32);
|
||||
p_data -= 32;data_len += 32;
|
||||
|
||||
p_data[-1] = 0x3;
|
||||
p_data[-2] = 0x3; // tls version
|
||||
p_data -= 2;data_len += 2;
|
||||
|
||||
p_data[-1] = data_len;
|
||||
p_data[-2] = data_len >> 8;
|
||||
p_data[-3] = 0x00;
|
||||
p_data[-4] = 0x02;
|
||||
p_data -= 4; data_len += 4;
|
||||
|
||||
p_data[-1] = data_len;
|
||||
p_data[-2] = data_len >> 8;
|
||||
p_data[-3] = 0x03;
|
||||
p_data[-4] = 0x03;
|
||||
p_data[-5] = 0x16;
|
||||
p_data -= 5; data_len += 5;
|
||||
|
||||
memcpy(out_buffer, p_data, data_len);
|
||||
char *pdata = out_buffer + 86;
|
||||
|
||||
memcpy(pdata, "\x14\x03\x03\x00\x01\x01", 6);
|
||||
pdata += 6;
|
||||
memcpy(pdata, "\x16\x03\x03\x00\x20", 5);
|
||||
pdata += 5;
|
||||
rand_bytes((uint8_t*)pdata, 22);
|
||||
pdata += 22;
|
||||
|
||||
uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
memcpy(key, self->server.key, self->server.key_len);
|
||||
memcpy(key + self->server.key_len, global->local_client_id, 32);
|
||||
ss_sha1_hmac_with_key(hash, out_buffer, 43 + 86, key, self->server.key_len + 32);
|
||||
free(key);
|
||||
memcpy(pdata, hash, OBFS_HMAC_SHA1_LEN);
|
||||
|
||||
memmove(encryptdata, out_buffer, 43 + 86);
|
||||
free(out_buffer);
|
||||
return 43 + 86;
|
||||
}
|
||||
|
||||
int tls12_ticket_auth_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
|
||||
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data;
|
||||
|
||||
*needsendback = 0;
|
||||
|
||||
if (local->handshake_status == 8) {
|
||||
local->recv_buffer_size += datalength;
|
||||
local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size);
|
||||
memcpy(local->recv_buffer + local->recv_buffer_size - datalength, encryptdata, datalength);
|
||||
datalength = 0;
|
||||
while (local->recv_buffer_size > 5) {
|
||||
if (local->recv_buffer[0] != 0x17)
|
||||
return -1;
|
||||
int size = ((int)(unsigned char)local->recv_buffer[3] << 8) + (unsigned char)local->recv_buffer[4];
|
||||
if (size + 5 > local->recv_buffer_size)
|
||||
break;
|
||||
if (*capacity < datalength + size) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + size) * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memcpy(encryptdata + datalength, local->recv_buffer + 5, size);
|
||||
datalength += size;
|
||||
local->recv_buffer_size -= 5 + size;
|
||||
memmove(local->recv_buffer, local->recv_buffer + 5 + size, local->recv_buffer_size);
|
||||
}
|
||||
return datalength;
|
||||
}
|
||||
if (datalength < 11 + 32 + 1 + 32) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
memcpy(key, self->server.key, self->server.key_len);
|
||||
memcpy(key + self->server.key_len, global->local_client_id, 32);
|
||||
ss_sha1_hmac_with_key(hash, encryptdata + 11, 22, key, self->server.key_len + 32);
|
||||
free(key);
|
||||
|
||||
if (memcmp(encryptdata + 33, hash, OBFS_HMAC_SHA1_LEN)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*needsendback = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tls12_ticket_auth_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) {
|
||||
char *encryptdata = *pencryptdata;
|
||||
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
|
||||
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data;
|
||||
|
||||
*needsendback = 0;
|
||||
|
||||
if (local->handshake_status == 8) {
|
||||
if(datalength != 0)
|
||||
{
|
||||
local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size + datalength);
|
||||
memmove(local->recv_buffer + local->recv_buffer_size, encryptdata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
}
|
||||
datalength = 0;
|
||||
|
||||
while (local->recv_buffer_size > 5) {
|
||||
if (local->recv_buffer[0] != 0x17 || local->recv_buffer[1] != 0x03 || local->recv_buffer[2] != 0x03)
|
||||
{
|
||||
LOGE("server_decode data error, wrong tls version 3");
|
||||
return -1;
|
||||
}
|
||||
int size = ((int)(unsigned char)local->recv_buffer[3] << 8) + (unsigned char)local->recv_buffer[4];
|
||||
if (size + 5 > local->recv_buffer_size)
|
||||
break;
|
||||
if (*capacity < local->recv_buffer_size + size) {
|
||||
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = (local->recv_buffer_size + size) * 2);
|
||||
encryptdata = *pencryptdata;
|
||||
}
|
||||
memcpy(encryptdata + datalength, local->recv_buffer + 5, size);
|
||||
datalength += size;
|
||||
local->recv_buffer_size -= 5 + size;
|
||||
memmove(local->recv_buffer, local->recv_buffer + 5 + size, local->recv_buffer_size);
|
||||
}
|
||||
return datalength;
|
||||
}
|
||||
|
||||
if (local->handshake_status == 3) {
|
||||
|
||||
char *verify = encryptdata;
|
||||
|
||||
if(datalength < 43)
|
||||
{
|
||||
LOGE("server_decode data error, too short:%d", (int)datalength);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(encryptdata[0] != 0x14 || encryptdata[1] != 0x03 || encryptdata[2] != 0x03 || encryptdata[3] != 0x00 || encryptdata[4] != 0x01 || encryptdata[5] != 0x01)
|
||||
{
|
||||
LOGE("server_decode data error, wrong tls version");
|
||||
return -1;
|
||||
}
|
||||
|
||||
encryptdata += 6;
|
||||
|
||||
if(encryptdata[0] != 0x16 || encryptdata[1] != 0x03 || encryptdata[2] != 0x03 || encryptdata[3] != 0x00 || encryptdata[4] != 0x20)
|
||||
{
|
||||
LOGE("server_decode data error, wrong tls version 2");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
memcpy(key, self->server.key, self->server.key_len);
|
||||
memcpy(key + self->server.key_len, global->local_client_id, 32);
|
||||
ss_sha1_hmac_with_key(hash, verify, 33, key, self->server.key_len + 32);
|
||||
free(key);
|
||||
|
||||
if (memcmp(verify + 33, hash, OBFS_HMAC_SHA1_LEN) != 0) {
|
||||
LOGE("server_decode data error, hash Mismatch %d",(int)memcmp(verify + 33, hash, OBFS_HMAC_SHA1_LEN));
|
||||
return -1;
|
||||
}
|
||||
|
||||
local->recv_buffer_size = datalength - 43;
|
||||
local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size);
|
||||
memmove(local->recv_buffer, encryptdata + 37, datalength - 43);
|
||||
|
||||
local->handshake_status = 8;
|
||||
return tls12_ticket_auth_server_decode(self, pencryptdata, 0, capacity, needsendback);
|
||||
}
|
||||
|
||||
local->handshake_status = 2;
|
||||
if(encryptdata[0] != 0x16 || encryptdata[1] != 0x03 || encryptdata[2] != 0x01)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
encryptdata += 3;
|
||||
|
||||
{
|
||||
int size = ((int)(unsigned char)encryptdata[0] << 8) + (unsigned char)encryptdata[1];
|
||||
if(size != datalength - 5)
|
||||
{
|
||||
LOGE("tls_auth wrong tls head size");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
encryptdata += 2;
|
||||
|
||||
if(encryptdata[0] != 0x01 || encryptdata[1] != 0x00)
|
||||
{
|
||||
LOGE("tls_auth not client hello message");
|
||||
return -1;
|
||||
}
|
||||
|
||||
encryptdata += 2;
|
||||
|
||||
{
|
||||
int size = ((int)(unsigned char)encryptdata[0] << 8) + (unsigned char)encryptdata[1];
|
||||
if(size != datalength - 9)
|
||||
{
|
||||
LOGE("tls_auth wrong message size");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
encryptdata += 2;
|
||||
|
||||
if(encryptdata[0] != 0x03 || encryptdata[1] != 0x03)
|
||||
{
|
||||
LOGE("tls_auth wrong tls version");
|
||||
return -1;
|
||||
}
|
||||
|
||||
encryptdata += 2;
|
||||
|
||||
char *verifyid = encryptdata;
|
||||
|
||||
encryptdata += 32;
|
||||
|
||||
int sessionid_len = encryptdata[0];
|
||||
if(sessionid_len < 32)
|
||||
{
|
||||
LOGE("tls_auth wrong sessionid_len");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *sessionid = encryptdata + 1;
|
||||
memcpy(global->local_client_id , sessionid, sessionid_len);
|
||||
|
||||
uint8_t *key = (uint8_t*)malloc(self->server.key_len + sessionid_len);
|
||||
char hash[ONETIMEAUTH_BYTES * 2];
|
||||
memcpy(key, self->server.key, self->server.key_len);
|
||||
memcpy(key + self->server.key_len, global->local_client_id, sessionid_len);
|
||||
ss_sha1_hmac_with_key(hash, verifyid, 22, key, self->server.key_len + sessionid_len);
|
||||
free(key);
|
||||
|
||||
encryptdata += (sessionid_len + 1);
|
||||
|
||||
long utc_time = ((int)(unsigned char)verifyid[0] << 24) + ((int)(unsigned char)verifyid[1] << 16) + ((int)(unsigned char)verifyid[2] << 8) + (unsigned char)verifyid[3];
|
||||
time_t t = time(NULL);
|
||||
|
||||
|
||||
if (self->server.param && strlen(self->server.param) == 0)
|
||||
{
|
||||
self->server.param = NULL;
|
||||
}
|
||||
|
||||
int max_time_dif = 0;
|
||||
int time_dif = utc_time - t;
|
||||
if(self->server.param)
|
||||
{
|
||||
max_time_dif = atoi(self->server.param);
|
||||
}
|
||||
|
||||
if(max_time_dif > 0 && (time_dif < -max_time_dif || time_dif > max_time_dif || utc_time - global->startup_time < -max_time_dif / 2))
|
||||
{
|
||||
LOGE("tls_auth wrong time");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(verifyid + 22, hash, OBFS_HMAC_SHA1_LEN)) {
|
||||
LOGE("tls_auth wrong sha1");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int search_result = global->client_data->have_same_cmp(global->client_data, verifyid);
|
||||
if(search_result != 0)
|
||||
{
|
||||
LOGE("replay attack detect!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
global->client_data->add_back(global->client_data, verifyid);
|
||||
|
||||
encryptdata += 48;
|
||||
|
||||
*needsendback = 1;
|
||||
|
||||
return 0;
|
||||
}
|
20
shadowsocksr-libev/src/server/tls1.2_ticket.h
Normal file
20
shadowsocksr-libev/src/server/tls1.2_ticket.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* http_simple.h - Define shadowsocksR server's buffers and callbacks
|
||||
*
|
||||
* Copyright (C) 2015 - 2016, Break Wa11 <mmgac001@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _TLS1_2_TICKET_H
|
||||
#define _TLS1_2_TICKET_H
|
||||
|
||||
void * tls12_ticket_auth_init_data();
|
||||
obfs * tls12_ticket_auth_new_obfs();
|
||||
void tls12_ticket_auth_dispose(obfs *self);
|
||||
|
||||
int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity);
|
||||
int tls12_ticket_auth_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback);
|
||||
|
||||
int tls12_ticket_auth_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity);
|
||||
int tls12_ticket_auth_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback);
|
||||
|
||||
#endif // _TLS1_2_TICKET_H
|
1452
shadowsocksr-libev/src/server/udprelay.c
Normal file
1452
shadowsocksr-libev/src/server/udprelay.c
Normal file
File diff suppressed because it is too large
Load Diff
95
shadowsocksr-libev/src/server/udprelay.h
Normal file
95
shadowsocksr-libev/src/server/udprelay.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* udprelay.h - Define UDP relay's buffers and callbacks
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* This file is part of the shadowsocks-libev.
|
||||
*
|
||||
* shadowsocks-libev is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* shadowsocks-libev is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with shadowsocks-libev; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _UDPRELAY_H
|
||||
#define _UDPRELAY_H
|
||||
|
||||
#include <ev.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "encrypt.h"
|
||||
#include "jconf.h"
|
||||
#include "obfs.h"
|
||||
|
||||
#ifdef MODULE_REMOTE
|
||||
#include "resolv.h"
|
||||
#endif
|
||||
|
||||
#include "cache.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define MAX_UDP_PACKET_SIZE (65507)
|
||||
|
||||
#define DEFAULT_PACKET_SIZE 1397 // 1492 - 1 - 28 - 2 - 64 = 1397, the default MTU for UDP relay
|
||||
|
||||
typedef struct server_ctx {
|
||||
ev_io io;
|
||||
int fd;
|
||||
int method;
|
||||
int auth;
|
||||
int timeout;
|
||||
const char *iface;
|
||||
struct cache *conn_cache;
|
||||
#ifdef MODULE_LOCAL
|
||||
const struct sockaddr *remote_addr;
|
||||
int remote_addr_len;
|
||||
#ifdef MODULE_TUNNEL
|
||||
ss_addr_t tunnel_addr;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef MODULE_REMOTE
|
||||
struct ev_loop *loop;
|
||||
#endif
|
||||
// SSR
|
||||
obfs *protocol;
|
||||
obfs_class *protocol_plugin;
|
||||
void *protocol_global;
|
||||
} server_ctx_t;
|
||||
|
||||
#ifdef MODULE_REMOTE
|
||||
typedef struct query_ctx {
|
||||
struct ResolvQuery *query;
|
||||
struct sockaddr_storage src_addr;
|
||||
buffer_t *buf;
|
||||
int addr_header_len;
|
||||
char addr_header[384];
|
||||
struct server_ctx *server_ctx;
|
||||
struct remote_ctx *remote_ctx;
|
||||
} query_ctx_t;
|
||||
#endif
|
||||
|
||||
typedef struct remote_ctx {
|
||||
ev_io io;
|
||||
ev_timer watcher;
|
||||
int af;
|
||||
int fd;
|
||||
int addr_header_len;
|
||||
char addr_header[384];
|
||||
struct sockaddr_storage src_addr;
|
||||
#ifdef MODULE_REMOTE
|
||||
struct sockaddr_storage dst_addr;
|
||||
#endif
|
||||
struct server_ctx *server_ctx;
|
||||
} remote_ctx_t;
|
||||
|
||||
#endif // _UDPRELAY_H
|
1074
shadowsocksr-libev/src/server/uthash.h
Normal file
1074
shadowsocksr-libev/src/server/uthash.h
Normal file
File diff suppressed because it is too large
Load Diff
448
shadowsocksr-libev/src/server/utils.c
Normal file
448
shadowsocksr-libev/src/server/utils.c
Normal file
@ -0,0 +1,448 @@
|
||||
/*
|
||||
* utils.c - Misc utilities
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* This file is part of the shadowsocks-libev.
|
||||
*
|
||||
* shadowsocks-libev is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* shadowsocks-libev is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with shadowsocks-libev; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#ifndef __MINGW32__
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef HAVE_SETRLIMIT
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#define INT_DIGITS 19 /* enough for 64 bit integer */
|
||||
|
||||
#ifdef LIB_ONLY
|
||||
FILE *logfile;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_SYSLOG
|
||||
int use_syslog = 0;
|
||||
#endif
|
||||
|
||||
#ifndef __MINGW32__
|
||||
void
|
||||
ERROR(const char *s)
|
||||
{
|
||||
char *msg = strerror(errno);
|
||||
LOGE("%s: %s", s, msg);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int use_tty = 1;
|
||||
|
||||
char *
|
||||
ss_itoa(int i)
|
||||
{
|
||||
/* Room for INT_DIGITS digits, - and '\0' */
|
||||
static char buf[INT_DIGITS + 2];
|
||||
char *p = buf + INT_DIGITS + 1; /* points to terminating '\0' */
|
||||
if (i >= 0) {
|
||||
do {
|
||||
*--p = '0' + (i % 10);
|
||||
i /= 10;
|
||||
} while (i != 0);
|
||||
return p;
|
||||
} else { /* i < 0 */
|
||||
do {
|
||||
*--p = '0' - (i % 10);
|
||||
i /= 10;
|
||||
} while (i != 0);
|
||||
*--p = '-';
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
int
|
||||
ss_isnumeric(const char *s) {
|
||||
if (!s || !*s)
|
||||
return 0;
|
||||
while (isdigit(*s))
|
||||
++s;
|
||||
return *s == '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* setuid() and setgid() for a specified user.
|
||||
*/
|
||||
int
|
||||
run_as(const char *user)
|
||||
{
|
||||
#ifndef __MINGW32__
|
||||
if (user[0]) {
|
||||
/* Convert user to a long integer if it is a non-negative number.
|
||||
* -1 means it is a user name. */
|
||||
long uid = -1;
|
||||
if (ss_isnumeric(user)) {
|
||||
errno = 0;
|
||||
char *endptr;
|
||||
uid = strtol(user, &endptr, 10);
|
||||
if (errno || endptr == user)
|
||||
uid = -1;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GETPWNAM_R
|
||||
struct passwd pwdbuf, *pwd;
|
||||
memset(&pwdbuf, 0, sizeof(struct passwd));
|
||||
size_t buflen;
|
||||
int err;
|
||||
|
||||
for (buflen = 128;; buflen *= 2) {
|
||||
char buf[buflen]; /* variable length array */
|
||||
|
||||
/* Note that we use getpwnam_r() instead of getpwnam(),
|
||||
* which returns its result in a statically allocated buffer and
|
||||
* cannot be considered thread safe. */
|
||||
err = uid >= 0 ? getpwuid_r((uid_t)uid, &pwdbuf, buf, buflen, &pwd)
|
||||
: getpwnam_r(user, &pwdbuf, buf, buflen, &pwd);
|
||||
|
||||
if (err == 0 && pwd) {
|
||||
/* setgid first, because we may not be allowed to do it anymore after setuid */
|
||||
if (setgid(pwd->pw_gid) != 0) {
|
||||
LOGE(
|
||||
"Could not change group id to that of run_as user '%s': %s",
|
||||
pwd->pw_name, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) {
|
||||
LOGE("Could not change supplementary groups for user '%s'.", pwd->pw_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (setuid(pwd->pw_uid) != 0) {
|
||||
LOGE(
|
||||
"Could not change user id to that of run_as user '%s': %s",
|
||||
pwd->pw_name, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
} else if (err != ERANGE) {
|
||||
if (err) {
|
||||
LOGE("run_as user '%s' could not be found: %s", user,
|
||||
strerror(err));
|
||||
} else {
|
||||
LOGE("run_as user '%s' could not be found.", user);
|
||||
}
|
||||
return 0;
|
||||
} else if (buflen >= 16 * 1024) {
|
||||
/* If getpwnam_r() seems defective, call it quits rather than
|
||||
* keep on allocating ever larger buffers until we crash. */
|
||||
LOGE(
|
||||
"getpwnam_r() requires more than %u bytes of buffer space.",
|
||||
(unsigned)buflen);
|
||||
return 0;
|
||||
}
|
||||
/* Else try again with larger buffer. */
|
||||
}
|
||||
#else
|
||||
/* No getpwnam_r() :-( We'll use getpwnam() and hope for the best. */
|
||||
struct passwd *pwd;
|
||||
|
||||
if (!(pwd = uid >=0 ? getpwuid((uid_t)uid) : getpwnam(user))) {
|
||||
LOGE("run_as user %s could not be found.", user);
|
||||
return 0;
|
||||
}
|
||||
/* setgid first, because we may not allowed to do it anymore after setuid */
|
||||
if (setgid(pwd->pw_gid) != 0) {
|
||||
LOGE("Could not change group id to that of run_as user '%s': %s",
|
||||
pwd->pw_name, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) {
|
||||
LOGE("Could not change supplementary groups for user '%s'.", pwd->pw_name);
|
||||
return 0;
|
||||
}
|
||||
if (setuid(pwd->pw_uid) != 0) {
|
||||
LOGE("Could not change user id to that of run_as user '%s': %s",
|
||||
pwd->pw_name, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // __MINGW32__
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *
|
||||
ss_strndup(const char *s, size_t n)
|
||||
{
|
||||
size_t len = strlen(s);
|
||||
char *ret;
|
||||
|
||||
if (len <= n) {
|
||||
return strdup(s);
|
||||
}
|
||||
|
||||
ret = ss_malloc(n + 1);
|
||||
strncpy(ret, s, n);
|
||||
ret[n] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
FATAL(const char *msg)
|
||||
{
|
||||
LOGE("%s", msg);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void *
|
||||
ss_malloc(size_t size)
|
||||
{
|
||||
void *tmp = malloc(size);
|
||||
if (tmp == NULL)
|
||||
exit(EXIT_FAILURE);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void *
|
||||
ss_realloc(void *ptr, size_t new_size)
|
||||
{
|
||||
void *new = realloc(ptr, new_size);
|
||||
if (new == NULL) {
|
||||
free(ptr);
|
||||
ptr = NULL;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
printf("\n");
|
||||
printf("shadowsocks-libev %s with %s\n\n", VERSION, USING_CRYPTO);
|
||||
printf(
|
||||
" maintained by Max Lv <max.c.lv@gmail.com> and Linus Yang <laokongzi@gmail.com>\n\n");
|
||||
printf(" usage:\n\n");
|
||||
#ifdef MODULE_LOCAL
|
||||
printf(" ss-local\n");
|
||||
#elif MODULE_REMOTE
|
||||
printf(" ss-server\n");
|
||||
#elif MODULE_TUNNEL
|
||||
printf(" ss-tunnel\n");
|
||||
#elif MODULE_REDIR
|
||||
printf(" ss-redir\n");
|
||||
#elif MODULE_MANAGER
|
||||
printf(" ss-manager\n");
|
||||
#endif
|
||||
printf("\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(
|
||||
" -l <local_port> Port number of your local server.\n");
|
||||
printf(
|
||||
" -k <password> Password of your remote server.\n");
|
||||
printf(
|
||||
" -m <encrypt_method> Encrypt method: table, rc4, rc4-md5,\n");
|
||||
printf(
|
||||
" aes-128-cfb, aes-192-cfb, aes-256-cfb,\n");
|
||||
printf(
|
||||
" aes-128-ctr, aes-192-ctr, aes-256-ctr,\n");
|
||||
printf(
|
||||
" bf-cfb, camellia-128-cfb, camellia-192-cfb,\n");
|
||||
printf(
|
||||
" camellia-256-cfb, cast5-cfb, des-cfb,\n");
|
||||
printf(
|
||||
" idea-cfb, rc2-cfb, seed-cfb, salsa20,\n");
|
||||
printf(
|
||||
" chacha20 and chacha20-ietf.\n");
|
||||
printf(
|
||||
" The default cipher is rc4-md5.\n");
|
||||
printf("\n");
|
||||
printf(
|
||||
" [-a <user>] Run as another user.\n");
|
||||
printf(
|
||||
" [-f <pid_file>] The file path to store pid.\n");
|
||||
printf(
|
||||
" [-t <timeout>] Socket timeout in seconds.\n");
|
||||
printf(
|
||||
" [-c <config_file>] The path to config file.\n");
|
||||
#ifdef HAVE_SETRLIMIT
|
||||
printf(
|
||||
" [-n <number>] Max number of open files.\n");
|
||||
#endif
|
||||
#ifndef MODULE_REDIR
|
||||
printf(
|
||||
" [-i <interface>] Network interface to bind.\n");
|
||||
#endif
|
||||
printf(
|
||||
" [-b <local_address>] Local address to bind.\n");
|
||||
printf("\n");
|
||||
printf(
|
||||
" [-u] Enable UDP relay.\n");
|
||||
#ifdef MODULE_REDIR
|
||||
printf(
|
||||
" TPROXY is required in redir mode.\n");
|
||||
#endif
|
||||
printf(
|
||||
" [-U] Enable UDP relay and disable TCP relay.\n");
|
||||
printf(
|
||||
" [-A] Enable onetime authentication.\n");
|
||||
#ifdef MODULE_REMOTE
|
||||
printf(
|
||||
" [-6] Resovle hostname to IPv6 address first.\n");
|
||||
#endif
|
||||
printf("\n");
|
||||
#ifdef MODULE_TUNNEL
|
||||
printf(
|
||||
" [-L <addr>:<port>] Destination server address and port\n");
|
||||
printf(
|
||||
" for local port forwarding.\n");
|
||||
#endif
|
||||
#ifdef MODULE_REMOTE
|
||||
printf(
|
||||
" [-d <addr>] Name servers for internal DNS resolver.\n");
|
||||
#endif
|
||||
#if defined(MODULE_REMOTE) || defined(MODULE_LOCAL)
|
||||
printf(
|
||||
" [--fast-open] Enable TCP fast open.\n");
|
||||
printf(
|
||||
" with Linux kernel > 3.7.0.\n");
|
||||
printf(
|
||||
" [--acl <acl_file>] Path to ACL (Access Control List).\n");
|
||||
#endif
|
||||
#if defined(MODULE_REMOTE) || defined(MODULE_MANAGER)
|
||||
printf(
|
||||
" [--manager-address <addr>] UNIX domain socket address.\n");
|
||||
#endif
|
||||
#ifdef MODULE_MANAGER
|
||||
printf(
|
||||
" [--executable <path>] Path to the executable of ss-server.\n");
|
||||
#endif
|
||||
printf(
|
||||
" [--mtu <MTU>] MTU of your network interface.\n");
|
||||
#ifdef __linux__
|
||||
printf(
|
||||
" [--mptcp] Enable Multipath TCP on MPTCP Kernel.\n");
|
||||
#ifdef MODULE_REMOTE
|
||||
printf(
|
||||
" [--firewall] Setup firewall rules for auto blocking.\n");
|
||||
#endif
|
||||
#endif
|
||||
printf("\n");
|
||||
printf(
|
||||
" [-v] Verbose mode.\n");
|
||||
printf(
|
||||
" [-h, --help] Print this message.\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void
|
||||
daemonize(const char *path)
|
||||
{
|
||||
#ifndef __MINGW32__
|
||||
/* Our process ID and Session ID */
|
||||
pid_t pid, sid;
|
||||
|
||||
/* Fork off the parent process */
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* If we got a good PID, then
|
||||
* we can exit the parent process. */
|
||||
if (pid > 0) {
|
||||
FILE *file = fopen(path, "w");
|
||||
if (file == NULL) {
|
||||
FATAL("Invalid pid file\n");
|
||||
}
|
||||
|
||||
fprintf(file, "%d", (int)pid);
|
||||
fclose(file);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* Change the file mode mask */
|
||||
umask(0);
|
||||
|
||||
/* Open any logs here */
|
||||
|
||||
/* Create a new SID for the child process */
|
||||
sid = setsid();
|
||||
if (sid < 0) {
|
||||
/* Log the failure */
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Change the current working directory */
|
||||
if ((chdir("/")) < 0) {
|
||||
/* Log the failure */
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Close out the standard file descriptors */
|
||||
close(STDIN_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_SETRLIMIT
|
||||
int
|
||||
set_nofile(int nofile)
|
||||
{
|
||||
struct rlimit limit = { nofile, nofile }; /* set both soft and hard limit */
|
||||
|
||||
if (nofile <= 0) {
|
||||
FATAL("nofile must be greater than 0\n");
|
||||
}
|
||||
|
||||
if (setrlimit(RLIMIT_NOFILE, &limit) < 0) {
|
||||
if (errno == EPERM) {
|
||||
LOGE(
|
||||
"insufficient permission to change NOFILE, not starting as root?");
|
||||
return -1;
|
||||
} else if (errno == EINVAL) {
|
||||
LOGE("invalid nofile, decrease nofile and try again");
|
||||
return -1;
|
||||
} else {
|
||||
LOGE("setrlimit failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
232
shadowsocksr-libev/src/server/utils.h
Normal file
232
shadowsocksr-libev/src/server/utils.h
Normal file
@ -0,0 +1,232 @@
|
||||
/*
|
||||
* utils.h - Misc utilities
|
||||
*
|
||||
* Copyright (C) 2013 - 2016, Max Lv <max.c.lv@gmail.com>
|
||||
*
|
||||
* This file is part of the shadowsocks-libev.
|
||||
*
|
||||
* shadowsocks-libev is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* shadowsocks-libev is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with shadowsocks-libev; see the file COPYING. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
|
||||
#include <openssl/opensslv.h>
|
||||
#define USING_CRYPTO OPENSSL_VERSION_TEXT
|
||||
|
||||
#elif defined(USE_CRYPTO_POLARSSL)
|
||||
#include <polarssl/version.h>
|
||||
#define USING_CRYPTO POLARSSL_VERSION_STRING_FULL
|
||||
|
||||
#elif defined(USE_CRYPTO_MBEDTLS)
|
||||
#include <mbedtls/version.h>
|
||||
#define USING_CRYPTO MBEDTLS_VERSION_STRING_FULL
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _UTILS_H
|
||||
#define _UTILS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#define PORTSTRLEN 16
|
||||
#define SS_ADDRSTRLEN (INET6_ADDRSTRLEN + PORTSTRLEN + 1)
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#define USE_TTY()
|
||||
#define USE_SYSLOG(ident)
|
||||
#define LOGI(...) \
|
||||
((void)__android_log_print(ANDROID_LOG_DEBUG, "shadowsocks", \
|
||||
__VA_ARGS__))
|
||||
#define LOGE(...) \
|
||||
((void)__android_log_print(ANDROID_LOG_ERROR, "shadowsocks", \
|
||||
__VA_ARGS__))
|
||||
|
||||
#else
|
||||
|
||||
#define STR(x) # x
|
||||
#define TOSTR(x) STR(x)
|
||||
|
||||
#ifdef LIB_ONLY
|
||||
|
||||
extern FILE *logfile;
|
||||
|
||||
#define TIME_FORMAT "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
#define USE_TTY()
|
||||
|
||||
#define USE_SYSLOG(ident)
|
||||
|
||||
#define USE_LOGFILE(ident) \
|
||||
do { \
|
||||
if (ident != NULL) { logfile = fopen(ident, "w+"); } } \
|
||||
while (0)
|
||||
|
||||
#define CLOSE_LOGFILE \
|
||||
do { \
|
||||
if (logfile != NULL) { fclose(logfile); } } \
|
||||
while (0)
|
||||
|
||||
#define LOGI(format, ...) \
|
||||
do { \
|
||||
if (logfile != NULL) { \
|
||||
time_t now = time(NULL); \
|
||||
char timestr[20]; \
|
||||
strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \
|
||||
fprintf(logfile, " %s INFO: " format "\n", timestr, ## __VA_ARGS__); \
|
||||
fflush(logfile); } \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define LOGE(format, ...) \
|
||||
do { \
|
||||
if (logfile != NULL) { \
|
||||
time_t now = time(NULL); \
|
||||
char timestr[20]; \
|
||||
strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \
|
||||
fprintf(logfile, " %s ERROR: " format "\n", timestr, \
|
||||
## __VA_ARGS__); \
|
||||
fflush(logfile); } \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
#define TIME_FORMAT "%Y-%m-%d %H:%M:%S"
|
||||
|
||||
#define USE_TTY()
|
||||
|
||||
#define USE_SYSLOG(ident)
|
||||
|
||||
#define LOGI(format, ...) \
|
||||
do { \
|
||||
time_t now = time(NULL); \
|
||||
char timestr[20]; \
|
||||
strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \
|
||||
fprintf(stderr, " %s INFO: " format "\n", timestr, ## __VA_ARGS__); \
|
||||
fflush(stderr); } \
|
||||
while (0)
|
||||
|
||||
#define LOGE(format, ...) \
|
||||
do { \
|
||||
time_t now = time(NULL); \
|
||||
char timestr[20]; \
|
||||
strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \
|
||||
fprintf(stderr, " %s ERROR: " format "\n", timestr, ## __VA_ARGS__); \
|
||||
fflush(stderr); } \
|
||||
while (0)
|
||||
|
||||
#else
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
extern int use_tty;
|
||||
#define USE_TTY() \
|
||||
do { \
|
||||
use_tty = isatty(STDERR_FILENO); \
|
||||
} while (0) \
|
||||
|
||||
#define HAS_SYSLOG
|
||||
extern int use_syslog;
|
||||
|
||||
#define TIME_FORMAT "%F %T"
|
||||
|
||||
#define USE_SYSLOG(ident) \
|
||||
do { \
|
||||
use_syslog = 1; \
|
||||
openlog((ident), LOG_CONS | LOG_PID, 0); } \
|
||||
while (0)
|
||||
|
||||
#define LOGI(format, ...) \
|
||||
do { \
|
||||
if (use_syslog) { \
|
||||
syslog(LOG_INFO, format, ## __VA_ARGS__); \
|
||||
} else { \
|
||||
time_t now = time(NULL); \
|
||||
char timestr[20]; \
|
||||
strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \
|
||||
if (use_tty) { \
|
||||
fprintf(stderr, "\e[01;32m %s INFO: \e[0m" format "\n", timestr, \
|
||||
## __VA_ARGS__); \
|
||||
} else { \
|
||||
fprintf(stderr, " %s INFO: " format "\n", timestr, \
|
||||
## __VA_ARGS__); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define LOGE(format, ...) \
|
||||
do { \
|
||||
if (use_syslog) { \
|
||||
syslog(LOG_ERR, format, ## __VA_ARGS__); \
|
||||
} else { \
|
||||
time_t now = time(NULL); \
|
||||
char timestr[20]; \
|
||||
strftime(timestr, 20, TIME_FORMAT, localtime(&now)); \
|
||||
if (use_tty) { \
|
||||
fprintf(stderr, "\e[01;35m %s ERROR: \e[0m" format "\n", timestr, \
|
||||
## __VA_ARGS__); \
|
||||
} else { \
|
||||
fprintf(stderr, " %s ERROR: " format "\n", timestr, \
|
||||
## __VA_ARGS__); \
|
||||
} \
|
||||
} } \
|
||||
while (0)
|
||||
|
||||
#endif
|
||||
/* _WIN32 */
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
|
||||
#ifdef ERROR
|
||||
#undef ERROR
|
||||
#endif
|
||||
#define ERROR(s) ss_error(s)
|
||||
|
||||
#else
|
||||
|
||||
void ERROR(const char *s);
|
||||
|
||||
#endif
|
||||
|
||||
char *ss_itoa(int i);
|
||||
int ss_isnumeric(const char *s);
|
||||
int run_as(const char *user);
|
||||
void FATAL(const char *msg);
|
||||
void usage(void);
|
||||
void daemonize(const char *path);
|
||||
char *ss_strndup(const char *s, size_t n);
|
||||
#ifdef HAVE_SETRLIMIT
|
||||
int set_nofile(int nofile);
|
||||
#endif
|
||||
|
||||
void *ss_malloc(size_t size);
|
||||
void *ss_realloc(void *ptr, size_t new_size);
|
||||
|
||||
#define ss_free(ptr) \
|
||||
do { \
|
||||
free(ptr); \
|
||||
ptr = NULL; \
|
||||
} while (0)
|
||||
|
||||
#endif // _UTILS_H
|
188
shadowsocksr-libev/src/server/verify.c
Normal file
188
shadowsocksr-libev/src/server/verify.c
Normal file
@ -0,0 +1,188 @@
|
||||
|
||||
#include "verify.h"
|
||||
|
||||
static int verify_simple_pack_unit_size = 2000;
|
||||
|
||||
typedef struct verify_simple_local_data {
|
||||
char * recv_buffer;
|
||||
int recv_buffer_size;
|
||||
}verify_simple_local_data;
|
||||
|
||||
void verify_simple_local_data_init(verify_simple_local_data* local) {
|
||||
local->recv_buffer = (char*)malloc(16384);
|
||||
local->recv_buffer_size = 0;
|
||||
}
|
||||
|
||||
obfs * verify_simple_new_obfs() {
|
||||
obfs * self = new_obfs();
|
||||
self->l_data = malloc(sizeof(verify_simple_local_data));
|
||||
verify_simple_local_data_init((verify_simple_local_data*)self->l_data);
|
||||
return self;
|
||||
}
|
||||
|
||||
void verify_simple_dispose(obfs *self) {
|
||||
verify_simple_local_data *local = (verify_simple_local_data*)self->l_data;
|
||||
if (local->recv_buffer != NULL) {
|
||||
free(local->recv_buffer);
|
||||
local->recv_buffer = NULL;
|
||||
}
|
||||
free(local);
|
||||
self->l_data = NULL;
|
||||
dispose_obfs(self);
|
||||
}
|
||||
|
||||
int verify_simple_pack_data(char *data, int datalength, char *outdata) {
|
||||
unsigned char rand_len = (xorshift128plus() & 0xF) + 1;
|
||||
int out_size = rand_len + datalength + 6;
|
||||
outdata[0] = out_size >> 8;
|
||||
outdata[1] = out_size;
|
||||
outdata[2] = rand_len;
|
||||
memmove(outdata + rand_len + 2, data, datalength);
|
||||
fillcrc32((unsigned char *)outdata, out_size);
|
||||
return out_size;
|
||||
}
|
||||
|
||||
int verify_simple_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
//verify_simple_local_data *local = (verify_simple_local_data*)self->l_data;
|
||||
char * out_buffer = (char*)malloc(datalength * 2 + 32);
|
||||
char * buffer = out_buffer;
|
||||
char * data = plaindata;
|
||||
int len = datalength;
|
||||
int pack_len;
|
||||
while ( len > verify_simple_pack_unit_size ) {
|
||||
pack_len = verify_simple_pack_data(data, verify_simple_pack_unit_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += verify_simple_pack_unit_size;
|
||||
len -= verify_simple_pack_unit_size;
|
||||
}
|
||||
if (len > 0) {
|
||||
pack_len = verify_simple_pack_data(data, len, buffer);
|
||||
buffer += pack_len;
|
||||
}
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int verify_simple_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
verify_simple_local_data *local = (verify_simple_local_data*)self->l_data;
|
||||
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
|
||||
if (local->recv_buffer_size + datalength > 16384)
|
||||
return -1;
|
||||
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
|
||||
char * out_buffer = (char*)malloc(local->recv_buffer_size);
|
||||
char * buffer = out_buffer;
|
||||
while (local->recv_buffer_size > 2) {
|
||||
int length = ((int)recv_buffer[0] << 8) | recv_buffer[1];
|
||||
if (length >= 8192 || length < 7) {
|
||||
free(out_buffer);
|
||||
local->recv_buffer_size = 0;
|
||||
return -1;
|
||||
}
|
||||
if (length > local->recv_buffer_size)
|
||||
break;
|
||||
|
||||
int crc = crc32((unsigned char*)recv_buffer, length);
|
||||
if (crc != -1) {
|
||||
free(out_buffer);
|
||||
local->recv_buffer_size = 0;
|
||||
return -1;
|
||||
}
|
||||
int data_size = length - recv_buffer[2] - 6;
|
||||
memmove(buffer, recv_buffer + 2 + recv_buffer[2], data_size);
|
||||
buffer += data_size;
|
||||
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
|
||||
}
|
||||
int len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int verify_simple_server_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
//verify_simple_local_data *local = (verify_simple_local_data*)self->l_data;
|
||||
char * out_buffer = (char*)malloc(datalength * 2 + 32);
|
||||
char * buffer = out_buffer;
|
||||
char * data = plaindata;
|
||||
int len = datalength;
|
||||
int pack_len;
|
||||
while ( len > verify_simple_pack_unit_size ) {
|
||||
pack_len = verify_simple_pack_data(data, verify_simple_pack_unit_size, buffer);
|
||||
buffer += pack_len;
|
||||
data += verify_simple_pack_unit_size;
|
||||
len -= verify_simple_pack_unit_size;
|
||||
}
|
||||
if (len > 0) {
|
||||
pack_len = verify_simple_pack_data(data, len, buffer);
|
||||
buffer += pack_len;
|
||||
}
|
||||
len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
||||
|
||||
int verify_simple_server_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t *capacity) {
|
||||
char *plaindata = *pplaindata;
|
||||
verify_simple_local_data *local = (verify_simple_local_data*)self->l_data;
|
||||
uint8_t * recv_buffer = (uint8_t *)local->recv_buffer;
|
||||
if (local->recv_buffer_size + datalength > 16384)
|
||||
{
|
||||
LOGE("verify_simple: wrong buf length %d", local->recv_buffer_size + datalength);
|
||||
return -1;
|
||||
}
|
||||
memmove(recv_buffer + local->recv_buffer_size, plaindata, datalength);
|
||||
local->recv_buffer_size += datalength;
|
||||
|
||||
char * out_buffer = (char*)malloc(local->recv_buffer_size);
|
||||
char * buffer = out_buffer;
|
||||
while (local->recv_buffer_size > 2) {
|
||||
int length = ((int)recv_buffer[0] << 8) | recv_buffer[1];
|
||||
if (length >= 8192 || length < 7) {
|
||||
free(out_buffer);
|
||||
local->recv_buffer_size = 0;
|
||||
LOGE("verify_simple: wrong length %d", length);
|
||||
return -1;
|
||||
}
|
||||
if (length > local->recv_buffer_size)
|
||||
break;
|
||||
|
||||
int crc = crc32((unsigned char*)recv_buffer, length);
|
||||
if (crc != -1) {
|
||||
free(out_buffer);
|
||||
local->recv_buffer_size = 0;
|
||||
LOGE("verify_simple: wrong crc");
|
||||
return -1;
|
||||
}
|
||||
int data_size = length - recv_buffer[2] - 6;
|
||||
memmove(buffer, recv_buffer + 2 + recv_buffer[2], data_size);
|
||||
buffer += data_size;
|
||||
memmove(recv_buffer, recv_buffer + length, local->recv_buffer_size -= length);
|
||||
}
|
||||
int len = buffer - out_buffer;
|
||||
if (*capacity < len) {
|
||||
*pplaindata = (char*)realloc(*pplaindata, *capacity = len * 2);
|
||||
plaindata = *pplaindata;
|
||||
}
|
||||
memmove(plaindata, out_buffer, len);
|
||||
free(out_buffer);
|
||||
return len;
|
||||
}
|
19
shadowsocksr-libev/src/server/verify.h
Normal file
19
shadowsocksr-libev/src/server/verify.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* verify.h - Define shadowsocksR server's buffers and callbacks
|
||||
*
|
||||
* Copyright (C) 2015 - 2016, Break Wa11 <mmgac001@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef _VERIFY_H
|
||||
#define _VERIFY_H
|
||||
|
||||
obfs * verify_simple_new_obfs();
|
||||
void verify_simple_dispose(obfs *self);
|
||||
|
||||
int verify_simple_client_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
int verify_simple_client_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
|
||||
int verify_simple_server_pre_encrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
int verify_simple_server_post_decrypt(obfs *self, char **pplaindata, int datalength, size_t* capacity);
|
||||
|
||||
#endif // _VERIFY_H
|
Loading…
Reference in New Issue
Block a user