implement --user

fix @278
This commit is contained in:
clowwindy 2015-02-02 15:38:55 +08:00
parent da65d0a2ee
commit ae99698b4e
4 changed files with 48 additions and 9 deletions

View file

@ -183,3 +183,35 @@ def daemon_stop(pid_file):
sys.exit(1) sys.exit(1)
print('stopped') print('stopped')
os.unlink(pid_file) os.unlink(pid_file)
def set_user(username):
if username is None:
return
import pwd
import grp
try:
pwrec = pwd.getpwnam(username)
except KeyError:
logging.error('user not found: %s' % username)
raise
user = pwrec[0]
uid = pwrec[2]
gid = pwrec[3]
cur_uid = os.getuid()
if uid == cur_uid:
return
if cur_uid != 0:
logging.error('can not set user as nonroot user')
# will raise later
# inspired by supervisor
if hasattr(os, 'setgroups'):
groups = [grprec[2] for grprec in grp.getgrall() if user in grprec[3]]
groups.insert(0, gid)
os.setgroups(groups)
os.setgid(gid)
os.setuid(uid)

View file

@ -73,6 +73,7 @@ def main():
sys.exit(1) sys.exit(1)
signal.signal(signal.SIGINT, int_handler) signal.signal(signal.SIGINT, int_handler)
daemon.set_user(config.get('user', None))
loop.run() loop.run()
except (KeyboardInterrupt, IOError, OSError) as e: except (KeyboardInterrupt, IOError, OSError) as e:
logging.error(e) logging.error(e)

View file

@ -86,6 +86,8 @@ def main():
loop = eventloop.EventLoop() loop = eventloop.EventLoop()
dns_resolver.add_to_loop(loop) dns_resolver.add_to_loop(loop)
list(map(lambda s: s.add_to_loop(loop), tcp_servers + udp_servers)) list(map(lambda s: s.add_to_loop(loop), tcp_servers + udp_servers))
daemon.set_user(config.get('user', None))
loop.run() loop.run()
except (KeyboardInterrupt, IOError, OSError) as e: except (KeyboardInterrupt, IOError, OSError) as e:
logging.error(e) logging.error(e)

View file

@ -89,7 +89,11 @@ def check_config(config):
if config.get('password') in [b'mypassword']: if config.get('password') in [b'mypassword']:
logging.error('DON\'T USE DEFAULT PASSWORD! Please change it in your ' logging.error('DON\'T USE DEFAULT PASSWORD! Please change it in your '
'config.json!') 'config.json!')
exit(1) sys.exit(1)
if config.get('user', None) is not None:
if os.name != 'posix':
logging.error('user can be used only on Unix')
sys.exit(1)
def get_config(is_local): def get_config(is_local):
@ -97,11 +101,11 @@ def get_config(is_local):
format='%(levelname)-s: %(message)s') format='%(levelname)-s: %(message)s')
if is_local: if is_local:
shortopts = 'hd:s:b:p:k:l:m:c:t:vq' shortopts = 'hd:s:b:p:k:l:m:c:t:vq'
longopts = ['help', 'fast-open', 'pid-file=', 'log-file='] longopts = ['help', 'fast-open', 'pid-file=', 'log-file=', 'user=']
else: else:
shortopts = 'hd:s:p:k:m:c:t:vq' shortopts = 'hd:s:p:k:m:c:t:vq'
longopts = ['help', 'fast-open', 'pid-file=', 'log-file=', 'workers=', longopts = ['help', 'fast-open', 'pid-file=', 'log-file=', 'workers=',
'forbidden-ip='] 'forbidden-ip=', 'user=']
try: try:
config_path = find_config() config_path = find_config()
optlist, args = getopt.getopt(sys.argv[1:], shortopts, longopts) optlist, args = getopt.getopt(sys.argv[1:], shortopts, longopts)
@ -147,6 +151,8 @@ def get_config(is_local):
config['fast_open'] = True config['fast_open'] = True
elif key == '--workers': elif key == '--workers':
config['workers'] = int(value) config['workers'] = int(value)
elif key == '--user':
config['user'] = to_str(value)
elif key == '--forbidden-ip': elif key == '--forbidden-ip':
config['forbidden_ip'] = to_str(value).split(',') config['forbidden_ip'] = to_str(value).split(',')
elif key in ('-h', '--help'): elif key in ('-h', '--help'):
@ -247,9 +253,7 @@ def print_help(is_local):
def print_local_help(): def print_local_help():
print('''usage: sslocal [-h] -s SERVER_ADDR [-p SERVER_PORT] print('''usage: sslocal [OPTION]...
[-b LOCAL_ADDR] [-l LOCAL_PORT] -k PASSWORD [-m METHOD]
[-t TIMEOUT] [-c CONFIG] [--fast-open] [-v] -[d] [-q]
A fast tunnel proxy that helps you bypass firewalls. A fast tunnel proxy that helps you bypass firewalls.
You can supply configurations via either config file or command line arguments. You can supply configurations via either config file or command line arguments.
@ -270,6 +274,7 @@ General options:
-d start/stop/restart daemon mode -d start/stop/restart daemon mode
--pid-file PID_FILE pid file for daemon mode --pid-file PID_FILE pid file for daemon mode
--log-file LOG_FILE log file for daemon mode --log-file LOG_FILE log file for daemon mode
--user USER username to run as
-v, -vv verbose mode -v, -vv verbose mode
-q, -qq quiet mode, only show warnings/errors -q, -qq quiet mode, only show warnings/errors
@ -278,9 +283,7 @@ Online help: <https://github.com/shadowsocks/shadowsocks>
def print_server_help(): def print_server_help():
print('''usage: ssserver [-h] [-s SERVER_ADDR] [-p SERVER_PORT] -k PASSWORD print('''usage: ssserver [OPTION]...
-m METHOD [-t TIMEOUT] [-c CONFIG] [--fast-open]
[--workers WORKERS] [-v] [-d start] [-q]
A fast tunnel proxy that helps you bypass firewalls. A fast tunnel proxy that helps you bypass firewalls.
You can supply configurations via either config file or command line arguments. You can supply configurations via either config file or command line arguments.
@ -301,6 +304,7 @@ General options:
-d start/stop/restart daemon mode -d start/stop/restart daemon mode
--pid-file PID_FILE pid file for daemon mode --pid-file PID_FILE pid file for daemon mode
--log-file LOG_FILE log file for daemon mode --log-file LOG_FILE log file for daemon mode
--user USER username to run as
-v, -vv verbose mode -v, -vv verbose mode
-q, -qq quiet mode, only show warnings/errors -q, -qq quiet mode, only show warnings/errors