内容简介:用户/用户组:用户是授权和登录的主体,用户组方便组织授权会话记录/命令记录:实时监控在线用户操作,支持录像回放,可中断用户不良操作资产/资产树:采纳资产树组织资产,管理起来异常方便
开源堡垒机系统--jumpserver
跳板机jumpserver主要功能:
用户/用户组:用户是授权和登录的主体,用户组方便组织授权
会话记录/命令记录:实时监控在线用户操作,支持录像回放,可中断用户不良操作
资产/资产树:采纳资产树组织资产,管理起来异常方便
跨云部署:一个中心节点,各区域部署接入节点,统一管理
授权规则:使用资产树授权,当节点资产变化时,自动继承授权.
web终端:领先的Web Terminal方案,支持Windows
部署环境:
系统: CentOS 7.6
IP: 192.168.11.11
设置防火墙和selinux关闭:
systemctl disable firewalld
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/sysconfig/selinux
修改主机名:
hostnamectl --static set-hostname han [这条命令在centos7中是永久有效的]
部署步骤:
一. 准备 Python 3 和 Python 虚拟环境
1.1 安装依赖包
[root@han ~]# yum -y install wget sqlite-devel xz gcc automake zlib-devel openssl-devel epel-release git
1.2 安装 Python3.6
[root@han ~]# wget https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tar.xz
[root@han ~]# tar -xf Python-3.6.1.tar.xz
[root@han ~]# cd Python-3.6.1/
[root@han Python-3.6.1]# ./configure && make && make install
1.3 建立 Python 虚拟环境
#因为 CentOS 7 自带的是 Python2, 而 Yum 等 工具 依赖原来的 Python, 为了不扰乱原来的环境我们来使用 Python 虚拟环境
[root@han Python-3.6.1]# cd /opt
[root@han opt]# python3.6 -m venv py3
#执行source命令进入虚拟环境
[root@han opt]# source /opt/py3/bin/activate
#看到下面的提示符代表成功, 以后运行 Jumpserver 都要先运行以上 source 命令, 以下所有命令均在该虚拟环境中运行
(py3) [root@han opt]#
二. 安装 Jumpserver
2.1 下载或 Clone 项目
#项目提交较多 git clone 时较大, 你可以选择去 Github 项目页面直接下载zip包。
(py3) [root@han opt]# git clone --depth=1 https://github.com/jumpserver/jumpserver.git
2.2 安装依赖 RPM 包
(py3) [root@han opt]# cd jumpserver/requirements/
(py3) [root@han requirements]# yum -y install $(cat rpm_requirements.txt)
2.3 安装 Python 库依赖
(py3) [root@han requirements]# pip install --upgrade pip setuptools
#不要指定-i参数,因为镜像上面可能没有最新的包;如果执行报错,多执行几次即可
(py3) [root@han requirements]# pip install -r requirements.txt
#如果下载速度过慢,可以使用国内阿里源
#pip install --upgrade pip setuptools -i https://mirrors.aliyun.com/pypi/simple/
#pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
2.4 安装 Redis, Jumpserver 使用 Redis 做 cache 和 celery broke
(py3) [root@han requirements]# cd
(py3) [root@han ~]# yum -y install redis
(py3) [root@han ~]# systemctl start redis
(py3) [root@han ~]# systemctl enable redis
2.5 安装 MySQL
(py3) [root@han ~]# yum -y install mariadb mariadb-devel mariadb-server
(py3) [root@han ~]# systemctl start mariadb
(py3) [root@han ~]# systemctl enable mariadb
2.6 创建数据库 Jumpserver 并授权
#生成随机数据库密码
(py3) [root@han ~]# cd /opt/jumpserver/requirements/
#利用随机数生成一个随机密码
(py3) [root@han requirements]# DB_PASSWORD=`cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 24`
#彩色打印出密码
(py3) [root@han requirements]# echo -e "\033[31m 你的数据库密码是 $DB_PASSWORD \033[0m"
(py3) [root@han requirements]# mysql -uroot -e "create database jumpserver default charset 'utf8'; grant all on jumpserver.* to 'jumpserver'@'127.0.0.1' identified by '$DB_PASSWORD'; flush privileges;"
2.7 修改 Jumpserver 配置文件
(py3) [root@han requirements]# cd ..
#复制yml模板文件
(py3) [root@han jumpserver]# cp config_example.yml config.yml
#取随机数,并写入到root下面的.bashrc里面中
(py3) [root@han jumpserver]# SECRET_KEY=`cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 50`
(py3) [root@han jumpserver]# echo "SECRET_KEY=$SECRET_KEY" >> ~/.bashrc
(py3) [root@han jumpserver]# BOOTSTRAP_TOKEN=`cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 16`
(py3) [root@han jumpserver]# echo "BOOTSTRAP_TOKEN=$BOOTSTRAP_TOKEN" >> ~/.bashrc
#对config.yml文件进行修改配置
(py3) [root@han jumpserver]# sed -i "s/SECRET_KEY:/SECRET_KEY: $SECRET_KEY/g" /opt/jumpserver/config.yml
(py3) [root@han jumpserver]# sed -i "s/BOOTSTRAP_TOKEN:/BOOTSTRAP_TOKEN: $BOOTSTRAP_TOKEN/g" /opt/jumpserver/config.yml
(py3) [root@han jumpserver]# sed -i "s/# DEBUG: true/DEBUG: false/g" /opt/jumpserver/config.yml
(py3) [root@han jumpserver]# sed -i "s/# LOG_LEVEL: DEBUG/LOG_LEVEL: ERROR/g" /opt/jumpserver/config.yml
(py3) [root@han jumpserver]# sed -i "s/# SESSION_EXPIRE_AT_BROWSER_CLOSE: false/SESSION_EXPIRE_AT_BROWSER_CLOSE: true/g" /opt/jumpserver/config.yml
(py3) [root@han jumpserver]# sed -i "s/DB_PASSWORD: /DB_PASSWORD: $DB_PASSWORD/g" /opt/jumpserver/config.yml
#可以查看一下你写入的密码是否正确
(py3) [root@han jumpserver]# echo -e "\033[31m 你的SECRET_KEY是 $SECRET_KEY \033[0m"
(py3) [root@han jumpserver]# echo -e "\033[31m 你的BOOTSTRAP_TOKEN是 $BOOTSTRAP_TOKEN \033[0m"
#确认内容有没有错误
(py3) [root@han jumpserver]# cat config.yml
config.yml解释 # SECURITY WARNING: keep the secret key used in production secret! # 加密秘钥 生产环境中请修改为随机字符串, 请勿外泄 SECRET_KEY: # SECURITY WARNING: keep the bootstrap token used in production secret! # 预共享Token coco和guacamole用来注册服务账号, 不在使用原来的注册接受机制 BOOTSTRAP_TOKEN: # Development env open this, when error occur display the full process track, Production disable it # DEBUG 模式 开启DEBUG后遇到错误时可以看到更多日志 DEBUG: false # DEBUG, INFO, WARNING, ERROR, CRITICAL can set. See https://docs.djangoproject.com/en/1.10/topics/logging/ # 日志级别 LOG_LEVEL: ERROR # LOG_DIR: # Session expiration setting, Default 24 hour, Also set expired on on browser close # 浏览器Session过期时间, 默认24小时, 也可以设置浏览器关闭则过期 # SESSION_COOKIE_AGE: 86400 SESSION_EXPIRE_AT_BROWSER_CLOSE: true # Database setting, Support sqlite3, mysql, postgres .... # 数据库设置 # See https://docs.djangoproject.com/en/1.10/ref/settings/#databases # SQLite setting: # 使用单文件 sqlite 数据库 # DB_ENGINE: sqlite3 # DB_NAME: # MySQL or postgres setting like: # 使用 Mysql 作为数据库 DB_ENGINE: mysql DB_HOST: 127.0.0.1 DB_PORT: 3306 DB_USER: jumpserver DB_PASSWORD: DB_NAME: jumpserver # When Django start it will bind this host and port # ./manage.py runserver 127.0.0.1:8080 # 运行时绑定端口 HTTP_BIND_HOST: 0.0.0.0 HTTP_LISTEN_PORT: 8080 # Use Redis as broker for celery and web socket # Redis配置 REDIS_HOST: 127.0.0.1 REDIS_PORT: 6379 # REDIS_PASSWORD: # REDIS_DB_CELERY: 3 # REDIS_DB_CACHE: 4 # Use OpenID authorization # 使用OpenID 来进行认证设置 # BASE_SITE_URL: http://localhost:8080 # AUTH_OPENID: false # True or False # AUTH_OPENID_SERVER_URL: https://openid-auth-server.com/ # AUTH_OPENID_REALM_NAME: realm-name # AUTH_OPENID_CLIENT_ID: client-id # AUTH_OPENID_CLIENT_SECRET: client-secret # OTP settings # OTP/MFA 配置 # OTP_VALID_WINDOW: 0 # OTP_ISSUER_NAME: Jumpserver
2.8 运行 Jumpserver
#后台运行使用-d参数
(py3) [root@han jumpserver]# ./jms start all -d
#新版本更新了运行脚本,使用方式./jms start | stop | status all 后台运行请添加-d参数
#这里只是 Jumpserver, 没有 Web Terminal,所以访问 Web Terminal 会报错
浏览器访问 http://192.168.11.11:8080/
账号admin , 密码admin
三. 安装 SSH Server 和 WebSocket Server: Coco
3.1 下载或 Clone 项目
(py3) [root@han jumpserver]# cd /opt
(py3) [root@han opt]# git clone --depth=1 https://github.com/jumpserver/coco.git
3.2 安装依赖
#个人强迫想改名,你们可以不需要
(py3) [root@han opt]# mv coco-master/ coco
(py3) [root@han opt]# cd coco/requirements/
(py3) [root@han requirements]# yum -y install $(cat rpm_requirements.txt)
(py3) [root@han requirements]# pip install -r requirements.txt
#如果下载速度很慢,可以换国内源
#pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
3.3 修改配置文件并运行
(py3) [root@han requirements]# cd ..
(py3) [root@han coco]# cp config_example.yml config.yml
(py3) [root@han coco]# sed -i "s/BOOTSTRAP_TOKEN: <PleasgeChangeSameWithJumpserver>/BOOTSTRAP_TOKEN: $BOOTSTRAP_TOKEN/g" /opt/coco/config.yml
(py3) [root@han coco]# sed -i "s/# LOG_LEVEL: INFO/LOG_LEVEL: ERROR/g" /opt/coco/config.yml
#查看有没有改错
(py3) [root@han coco]# cat config.yml
config.yml解释 # 项目名称, 会用来向Jumpserver注册, 识别而已, 不能重复 # NAME: {{ Hostname }} # Jumpserver项目的url, api请求注册会使用 CORE_HOST: http://127.0.0.1:8080 # Bootstrap Token, 预共享秘钥, 用来注册coco使用的service account和terminal # 请和jumpserver 配置文件中保持一致, 注册完成后可以删除 BOOTSTRAP_TOKEN: <PleasgeChangeSameWithJumpserver> # 启动时绑定的ip, 默认 0.0.0.0 # BIND_HOST: 0.0.0.0 # 监听的SSH端口号, 默认2222 # SSHD_PORT: 2222 # 监听的HTTP/WS端口号, 默认5000 # HTTPD_PORT: 5000 # 项目使用的ACCESS KEY, 默认会注册, 并保存到 ACCESS_KEY_STORE中, # 如果有需求, 可以写到配置文件中, 格式 access_key_id:access_key_secret # ACCESS_KEY: null # ACCESS KEY 保存的地址, 默认注册后会保存到该文件中 # ACCESS_KEY_STORE: data/keys/.access_key # 加密密钥 # SECRET_KEY: null # 设置日志级别 [DEBUG, INFO, WARN, ERROR, FATAL, CRITICAL] LOG_LEVEL: ERROR # 日志存放的目录 # LOG_DIR: logs # SSH白名单 # ALLOW_SSH_USER: all # SSH黑名单, 如果用户同时在白名单和黑名单, 黑名单优先生效 # BLOCK_SSH_USER: # - # 和Jumpserver 保持心跳时间间隔 # HEARTBEAT_INTERVAL: 5 # Admin的名字, 出问题会提示给用户 # ADMINS: '' # SSH连接超时时间 (default 15 seconds) # SSH_TIMEOUT: 15 # 语言 [en, zh] # LANGUAGE_CODE: zh # SFTP的根目录, 可选 /tmp, Home其他自定义目录 # SFTP_ROOT: /tmp # SFTP是否显示隐藏文件 # SFTP_SHOW_HIDDEN_FILE: false
# 后台运行使用 -d 参数
(py3) [root@han coco]# ./cocod start -d
# 新版本更新了运行脚本, 使用方式./cocod start|stop|status 后台运行请添加 -d 参数
这时需要去 Jumpserver 管理后台-会话管理-终端管理(http://192.168.11.11:8080/terminal/terminal/)接受 Coco 的注册
#终端连接
(py3) [root@han coco]# ssh -p2222 admin@192.168.11.11
密码为admin,登录成功即显示下图
四. 安装 Web Terminal 前端: Luna
Luna 已改为纯前端, 需要 Nginx 来运行访问
访问(https://github.com/jumpserver/luna/releases)下载对应版本的 release 包, 直接解压不需要编译
4.1 解压 Luna
(py3) [root@han opt]# cd /opt
(py3) [root@han opt]# wget https://github.com/jumpserver/luna/releases/download/1.4.10/luna.tar.gz
# 如果网络有问题导致下载无法完成可以使用下面地址
# wget https://demo.jumpserver.org/download/luna/1.4.10/luna.tar.gz
(py3) [root@han opt]# tar -xf luna.tar.gz
#查看luna的属主和属组,我们发现并不是root,所以我们得修改
(py3) [root@han opt]# ll
(py3) [root@han opt]# chown -R root:root luna
五. 配置 Nginx 整合各组件
5.1 安装 Nginx
(py3) [root@han opt]# cat /etc/yum.repos.d/nginx.repo
[nginx-stable] name=nginx stable repo baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ gpgcheck=1 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key
(py3) [root@han opt]# yum makecache fast
(py3) [root@han opt]# yum install -y nginx
(py3) [root@han opt]# rm -rf /etc/nginx/conf.d/default.conf
(py3) [root@han opt]# systemctl enable nginx
5.2 准备配置文件
(py3) [root@han opt]# vim /etc/nginx/conf.d/jumpserver.conf
server { listen 80; # 代理端口, 以后将通过此端口进行访问, 不再通过8080端口 # server_name demo.jumpserver.org; # 修改成你的域名或者注释掉 client_max_body_size 100m; # 录像及文件上传大小限制 location /luna/ { try_files $uri / /index.html; alias /opt/luna/; # luna 路径, 如果修改安装目录, 此处需要修改 } location /media/ { add_header Content-Encoding gzip; root /opt/jumpserver/data/; # 录像位置, 如果修改安装目录, 此处需要修改 } location /static/ { root /opt/jumpserver/data/; # 静态资源, 如果修改安装目录, 此处需要修改 } location /socket.io/ { proxy_pass http://localhost:5000/socket.io/; # 如果coco安装在别的服务器, 请填写它的ip proxy_buffering off; 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; access_log off; } location /coco/ { proxy_pass http://localhost:5000/coco/; # 如果coco安装在别的服务器, 请填写它的ip proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; access_log off; } location /guacamole/ { proxy_pass http://localhost:8081/; # 如果guacamole安装在别的服务器, 请填写它的ip proxy_buffering off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $http_connection; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; access_log off; #client_max_body_size 100m; # windows 文件上传大小限制 } location / { proxy_pass http://localhost:8080; # 如果jumpserver安装在别的服务器, 请填写它的ip proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
5.3 运行 Nginx
# 确保配置没有问题, 有问题请先解决
(py3) [root@han opt]# nginx -t
# CentOS 7
(py3) [root@han opt]# systemctl start nginx
5.4 开始使用 Jumpserver
检查应用是否已经正常运行服务全部启动后, 访问 http://192.168.11.11, 访问nginx代理的端口, 不要再通过8080端口访问
默认账号: admin 密码: admin
到Jumpserver 会话管理-终端管理 检查 Coco Guacamole 等应用的注册。 如果登录客户端是 macOS 或 Linux, 登录语法如下 ssh -p2222 admin@192.168.11.11 sftp -P2222 admin@192.168.11.11 密码: admin 如果登录客户端是 Windows, Xshell Terminal 登录语法如下 ssh admin@192.168.11.11 2222 sftp admin@192.168.11.11 2222 密码: admin 如果能登陆代表部署成功 sftp默认上传的位置在资产的 /tmp 目录下 windows拖拽上传的位置在资产的 Guacamole RDP上的 G 目录下
安装过程中常见的错误:
1、git clone 提示 ssl 错误
# 一般是由于时间不同步, 或者网络有问题导致的 # 可以尝试下载 releases 包
2、pip install 提示 ssl 错误
# 参考第一条解决
3、pip install 提示 download 错误
# 一般是由于网络不好, 导致下载文件失败, 重新执行命令即可 # 如果多次重试均无效, 请更换网络环境
4、pip install 提示 Could not find a version that satisfies the requirement xxxxxx==x.x.xx(版本)
# 一般是由于镜像源未同步, -i 指定官方源即可, 如: $ pip install -r requirement.txt -i https://pypi.org/simple $ pip install xxxxx==x.x.xx -i https://pypi.org/simple
5、pip install 提示 install for mysqlclient ... error /usr/bin/ld: 找不到 -lmariadb
# 如果是 Mariadb 大于 10 版本 $ yum install MariaDB-shared
6、sh make_migrations.sh 时报错 from config import config as CONFIG File "/opt/jumpserver/config.yml", line 38
# 这是由于 config.yml 里面的内容格式不对, 请参考安装文档的说明, 把提示的内容与上一行对齐即可
7、sh make_migrations.sh 时报错 Are you sure it's installed and available on your PYTHONPATH environment variable? Did you forget to activate a virtual environment?
# 一般是由于 py3 环境未载入 $ source /opt/py3/bin/activate # 看到下面的提示符代表成功, 以后运行 Jumpserver 都要先运行以上 source 命令, 以下所有命令均在该虚拟环境中运行 (py3) [root@localhost py3] # 如果已经在 py3 虚拟环境下, 任然报 Are you sure it's installed and available on your PYTHONPATH environment variable? Did you forget to activate a virtual environment? $ cd /opt/jumpserver/requirements $ pip install -r requirements.txt # 然后重新执行 sh make_migrations.sh
8、sh make_migrations.sh 报错 CommandError: Conflicting migrations detected; multiple ... django_celery_beat ...
# 这是由于 django-celery-beat老版本有bug引起的 $ rm -rf /opt/py3/lib/python3.6/site-packages/django_celery_beat/migrations/ $ pip uninstall django-celery-beat $ pip install django-celery-beat
9、执行 ./jms start all 后一直卡在 beat: Waking up in 1.00 minute.
# 如果没有error提示进程无法启动, 那么这是正常现象 # 如果不想在前台启动, 可以使用 ./jms start all -d 在后台启动
10、执行 ./jms start all 后提示 xxx is stopped
# Error: xxx start error # xxx is stopped $ ./jms restart xxx # 如 ./jms restart gunicorn
11、执行 ./jms start all 后提示 WARNINGS: ?: (mysql.W002) MySQL Strict Mode is not set for database connection 'default' ...
# 这是严格模式的警告, 可以参考后面的url解决, 或者忽略
12、启动 Jumpserver 或者 coco 报错 Error: expected '<document start>', but found '<scalar>'
# 这是因为你的 config.yml 文件格式有误 # 常见的错误就是字段为空或者: 后面有一个空格 # SECRET_KEY: xxxxx # 不要忽略: 后面的空格
13、启动 jumpserver 后, 访问 8080 端口页面显示不正常
# 这是因为你在 config.yml 里面设置了 DEBUG: false # 跟着教程继续操作, 后面搭建 nginx 代理即可正常访问
14、执行 ./cocod start 后提示 No module named 'jms'
# 一般是由于 py3 环境未载入 $ source /opt/py3/bin/activate # 看到下面的提示符代表成功, 以后运行 Jumpserver 都要先运行以上 source 命令, 以下所有命令均在该虚拟环境中运行 (py3) [root@localhost py3] # 如果已经在 py3 虚拟环境下 $ cd /opt/coco/ $ pip install -r requirements/requirements.txt # 然后重新执行 ./cocod start 即可
15、执行 ./cocod start 后提示 Failed register terminal xxxx exist already
# 这是由于 coco 注册未成功造成的, 需要重新注册 (能正常访问 jumpserver 页面后再处理) # 到 Jumpserver后台 会话管理-终端管理 删掉 coco 的注册 # 必须到 Jumpserver后台 会话管理-终端管理 删掉 coco 的注册 # 一定要先到 Jumpserver后台 会话管理-终端管理 删掉 coco 的注册 $ cd /opt/coco && ./cocod stop $ rm /opt/coco/data/keys/.access_key # coco, 如果你是按文档安装的, key应该在这里, 如果不存在key文件直接下一步 $ ./cocod start -d # 正常运行后到Jumpserver 会话管理-终端管理 里面接受coco注册
16、执行 ./cocod start 后提示 Failed register terminal unknow: xxxx
# 这是因为当前系统的 hostname 有 coco 不支持的字符, 需要手动指定 coco 的 NAME $ cd /opt/coco/ $ vi config.yml # 项目名称, 会用来向Jumpserver注册, 识别而已, 不能重复 # NAME: {{ Hostname }} NAME: localhost # 保存后重新执行 ./cocod start 即可
17、运行 ./cocod start 后提示 "detail":"身份认证信息未提供。" Failed register terminal
# 保证 coco 的 BOOTSTRAP_TOKEN 与 jumpserver/config.yml 里面的内容不一致 $ cat /opt/jumpserver/config.yml | grep BOOTSTRAP_TOKEN $ cat /opt/coco/config.yml | grep BOOTSTRAP_TOKEN # 修改成一致保存后 重新执行 ./cocod start 即可
18、运行 ./cocod start 后提示 Connect endpoint http://xxxx:8080 error: HTTPConnectionPool(host='xxxx', port=8080)
# 这是因为 coco 无法连接到 jumpserver 报的错误, 确定 http://xxxx:8080 设置正确(配置文件 coco/config.yml) # 如果 jumpserver 的IP和端口不对, 请手动修改 config.yml 的 CORE_HOST
19、运行 ./cocod start 后提示 Unexpected error occur: 'AppService' object has no attribute 'get_system_user_cmd_filter_rules'
# 这是因为你的 pip 依赖包未正确安装, 参考本文档第 4 条
20、通过 nginx 代理的端口访问 jumpserver 页面显示不正常
# 这是因为你没有按照教程进行安装, 修改了安装目录, 需要在 nginx 的配置文件里面修改资源路径 $ vi /etc/nginx/conf.d/jumpserver.conf
21、访问 luna 页面提示 Luna是单独部署的一个程序, 你需要部署luna, coco, 配置nginx做url分发...
# 请通过 nginx 代理的端口访问 jumpserver 页面, 不要再直接访问 8080 端口
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 麒麟开源堡垒机 V1.51 发布,开源的堡垒机系统
- 开源堡垒机 Jumpserver 1.3 版本正式发布
- 开源 | Jumpserver:全球首款完全开源的堡垒机,9100+ Star
- 开源堡垒机 Jumpserver 1.4.1 发布,翻译优化
- 开源堡垒机 Jumpserver 1.2.1 发布,授权规则回归
- 开源堡垒机 Jumpserver 1.4.3 发布,支持命令过滤
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
HTML Dog
Patrick Griffiths / New Riders Press / 2006-11-22 / USD 49.99
For readers who want to design Web pages that load quickly, are easy to update, accessible to all, work on all browsers and can be quickly adapted to different media, this comprehensive guide represen......一起来看看 《HTML Dog》 这本书的介绍吧!