diff --git a/docs/nginx-with-ssl-configuration.md b/docs/nginx-with-ssl-configuration.md new file mode 100644 index 000000000..7d218ebea --- /dev/null +++ b/docs/nginx-with-ssl-configuration.md @@ -0,0 +1,75 @@ +# 使用Nginx搭建SSL配置 + +跳板机是所有服务器的入口,所以,它的安全至关重要。因此,建议把`Jumpserver`搭建在内网环境中,并且加上SSL证书,保证数据传输的安全。 + +## nginx的安装 + +不同的操作系统及版本,安装方法都不太一样。我们以`Debian`为例。 + +``` +apt-get update +apt-get install -y nginx +``` + +更多安装示例请参考 [Nginx官方安装指南](https://www.nginx.com/resources/wiki/start/topics/tutorials/install/) + +## Nginx中的SSL的配置 + +* 编辑 `/etc/nginx/sites-enabled/default` 或者指定的`Jumpserver`的配置文件 + +* 示例如下 + +``` +server { + listen 443; + listen 80; + server_name YOUR_DOMAIN; + ssl_certificate YOUR_DOMAIN_CRT; + ssl_certificate_key YOUR_DOMAIN_KEY; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers HIGH:!aNULL:!MD5; + ssl_prefer_server_ciphers on; + ssl on ; + + if ($ssl_protocol = "") { + rewrite ^ https://$host$request_uri? permanent; + } + + location / { + proxy_set_header Connection ""; + proxy_http_version 1.1; + proxy_pass http://JUMPSERVER_HOST:WEB_PORT; + } + + location /_ws/ { + keepalive_timeout 600s; + send_timeout 600s; + proxy_connect_timeout 7d; + proxy_send_timeout 7d; + proxy_read_timeout 7d; + rewrite ^/_ws(/.*)$ $1 break; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_pass http://JUMPSERVER_HOST:WS_PORT; + } +} + +``` + +* 请替换如下表格的关键字 + + +关键字 | 示例 | 说明 +------------- | ------------- |------- +`YOUR_DOMAIN` | example.com | `Jumpserver`的域名 +`YOUR_DOMAIN_CRT` | /etc/nginx/certs/example.crt | SSL证书的CRT文件 +`YOUR_DOMAIN_KEY` | /etc/nginx/certs/example.key | SSL证书的KEY文件 +`JUMPSERVER_HOST` | 127.0.0.1 | `Jumpserver`服务器IP +`WEB_PORT ` | 80 | `Jumpserver`网页监听端口 +`WS_PORT ` | 3000 | websocket端口,`Jumpserver` 默认为3000 + +* 此配置会强制使用`https`, 建议加上(即if判断的那三行)。 \ No newline at end of file diff --git a/run_server.py b/run_server.py index c8240ea9f..9fa8644a4 100755 --- a/run_server.py +++ b/run_server.py @@ -8,8 +8,10 @@ import os import sys import os.path import threading -import datetime import re +import functools + +from django.core.signals import request_started, request_finished import tornado.ioloop import tornado.options @@ -21,10 +23,10 @@ import tornado.httpclient from tornado.websocket import WebSocketClosedError from tornado.options import define, options -from pyinotify import WatchManager, Notifier, ProcessEvent, IN_DELETE, IN_CREATE, IN_MODIFY, AsyncNotifier +from pyinotify import WatchManager, ProcessEvent, IN_DELETE, IN_CREATE, IN_MODIFY, AsyncNotifier import select -from connect import Tty, User, Asset, PermRole, logger, get_object, PermRole, gen_resource +from connect import Tty, User, Asset, PermRole, logger, get_object, gen_resource from connect import TtyLog, Log, Session, user_have_perm, get_group_user_perm, MyRunner, ExecLog try: @@ -38,6 +40,16 @@ define("port", default=PORT, help="run on the given port", type=int) define("host", default=IP, help="run port on given host", type=str) +def django_request_support(func): + @functools.wraps(func) + def _deco(*args, **kwargs): + request_started.send_robust(func) + response = func(*args, **kwargs) + request_finished.send_robust(func) + return response + return _deco + + def require_auth(role='user'): def _deco(func): def _deco2(request, *args, **kwargs): @@ -58,6 +70,7 @@ def require_auth(role='user'): request.user = user if role == 'admin': if user.role in ['SU', 'GA']: + request_finished.send_robust() return func(request, *args, **kwargs) logger.debug('Websocket: user [ %s ] is not admin.' % user.username) else: @@ -69,6 +82,7 @@ def require_auth(role='user'): except AttributeError: pass logger.warning('Websocket: Request auth failed.') + return _deco2 return _deco @@ -129,6 +143,7 @@ class MonitorHandler(tornado.websocket.WebSocketHandler): def check_origin(self, origin): return True + @django_request_support @require_auth('admin') def open(self): # 获取监控的path @@ -180,6 +195,7 @@ class WebTty(Tty): class WebTerminalKillHandler(tornado.web.RequestHandler): + @django_request_support @require_auth('admin') def get(self): ws_id = self.get_argument('id') @@ -209,6 +225,7 @@ class ExecHandler(tornado.websocket.WebSocketHandler): def check_origin(self, origin): return True + @django_request_support @require_auth('user') def open(self): logger.debug('Websocket: Open exec request') @@ -289,6 +306,7 @@ class WebTerminalHandler(tornado.websocket.WebSocketHandler): def check_origin(self, origin): return True + @django_request_support @require_auth('user') def open(self): logger.debug('Websocket: Open request')