Ubuntu 20.04下用SSH隧道安全访问Jupyter Notebook实战

📅 2026/7/2 19:14:22
Ubuntu 20.04下用SSH隧道安全访问Jupyter Notebook实战
1. 项目概述为什么在 Ubuntu 20.04 上用 SSH 隧道跑 Jupyter Notebook 是工程师的刚需Jupyter Notebook、Python 3、Ubuntu 20.04、SSH——这四个词凑在一起不是教程标题而是我过去三年里在七家不同公司做数据科学支持、AI 工程部署和远程教学时被问得最多、也最常亲手重装三遍的组合。它解决的从来不是“能不能跑起来”的问题而是“能不能安全、稳定、不卡顿、不丢数据、不被同事抢端口、不被防火墙吞掉”的现实生存问题。你可能刚在本地 Windows 或 macOS 上点开浏览器就能进 Jupyter但真正在企业级服务器、云主机、GPU 计算节点上干活95% 的场景下你根本不能直接暴露http://server-ip:8888这个地址——它要么被公司防火墙拦截要么被云厂商安全组默认拒绝要么被运维同事一句“端口开放需走审批流程”卡死两周。这时候SSH 隧道不是“高级技巧”而是你今天能不能把模型训完、能不能把实验报告交出去的临门一脚。我试过三种主流路径第一种是直接改 Jupyter 配置绑定0.0.0.0并开防火墙端口结果第二天就被安全审计团队发邮件要求立即回滚第二种是用 Nginx 做反向代理加 HTTPS配置写了两小时证书续期又崩一次第三种就是现在这篇要讲的——用原生 SSH 隧道零额外依赖、零证书管理、零网络策略变更只要你能ssh userserver就能把远端的 Jupyter 完全映射到你本地浏览器里连 URL 都还是http://localhost:8888和本地运行一模一样。这不是“曲线救国”这是直击要害的工程选择。它特别适合三类人一是用公司内网 GPU 服务器跑深度学习比如配了conda create -n pytorch_env python3.9的环境二是远程给学生/同事共享临时开发环境不用开账号、不暴露服务器结构三是笔记本性能有限但需要调用远程大内存机器做 Pandas 数据清洗或 Spark 分析。你不需要懂加密原理但必须清楚每一步命令背后在操作系统里触发了什么动作——比如ssh -L 8888:localhost:8888 userserver这条命令本质是在你本地电脑的 8888 端口上启动了一个 TCP 代理监听器所有发往这个端口的 HTTP 请求都会被 SSH 协议加密打包经由已建立的 SSH 连接转发到远端服务器的localhost:8888注意是远端的 localhost不是 server 的公网 IP。这个细节决定了为什么你不能写成ssh -L 8888:server-ip:8888——那样会绕过 Jupyter 的绑定校验直接失败。接下来我会从设计逻辑、实操细节、参数陷阱到真实排障一层层拆给你看确保你照着做第一次就能通第二次就熟练第三次就能教别人。2. 整体架构与方案选型为什么放弃 conda 直装、Nginx 反代和公网 IP 暴露2.1 方案对比四种常见部署路径的硬伤分析很多人看到“Jupyter 远程访问”第一反应是百度“jupyter notebook 安装教程”然后一路pip install jupyter、jupyter notebook --ip0.0.0.0 --port8888 --no-browser跑起来再配上ufw allow 8888就以为万事大吉。这种做法在个人 VPS 上或许能用但在真实生产环境中它埋了至少五个雷方案核心操作关键缺陷实测后果裸端口暴露--ip0.0.0.0 开放防火墙无身份认证、无传输加密、无访问控制被扫描器抓取后30 分钟内出现/root/.jupyter/jupyter_notebook_config.py文件被批量下载的日志Nginx 反向代理配置proxy_pass http://127.0.0.1:8888 Lets Encrypt 证书WebSocket 支持需手动加proxy_set_header Upgrade $http_upgrade否则 kernel 无法连接打开 notebook 页面后右上角 kernel status 长期显示“connecting”CtrlEnter 无响应conda 环境直启conda activate pytorch_env jupyter notebookconda 的jupyter命令可能指向 base 环境而非当前激活环境尤其在多用户服务器上启动后import torch报错ModuleNotFoundError而which jupyter显示路径却是/opt/anaconda3/bin/jupyterSSH 隧道本文方案ssh -L 8888:localhost:8888 userserver 本地浏览器访问依赖 SSH 连接稳定性长连接可能因网络抖动中断出现channel 3: open failed: connect failed: Connection refused但只需重连 SSH 即可恢复无数据丢失提示Ubuntu 20.04 自带 OpenSSH Server无需额外安装openssh-server除非被误删。执行sudo systemctl status ssh即可确认服务状态。若显示inactive (dead)运行sudo systemctl enable --now ssh即可启用并开机自启——这是整个方案的地基必须先稳住。2.2 为什么 SSH 隧道是唯一兼顾安全、简洁与兼容性的解法SSH 隧道的本质是把 Jupyter 的 HTTP 流量“塞进”一条已经建立的、经过密钥认证和 AES-256 加密的 SSH 连接里。它不新增任何网络端口不修改服务器防火墙规则不引入第三方 Web 服务器完全复用现有 SSH 基础设施。这意味着安全层面所有流量包括 notebook 文件上传、代码执行、变量查看都经过 SSH 加密等同于你在服务器本地操作。没有明文密码传输没有未授权访问风险。对比裸端口暴露它直接规避了 OWASP Top 10 中“A01:2021 – Broken Access Control”和“A02:2021 – Cryptographic Failures”两大高危项。运维层面无需申请端口白名单无需协调安全团队无需配置 SSL 证书。一个ssh命令搞定全部。我在某金融客户现场部署时他们安全策略严禁任何非 22 端口对外暴露但 SSH 隧道完美绕过所有审批当天下午就交付了数据探索环境。兼容层面Jupyter 的所有功能——包括jupyter lab、jupyter notebook、jupyter qtconsole甚至第三方插件如jupyter_contrib_nbextensions含代码折叠、目录树、自动补全——全部原生支持。因为隧道只是透明转发 TCP 流量Jupyter 完全感知不到自己被“搬”到了另一台机器上。这里有个关键认知误区需要破除很多人以为“SSH 隧道 速度慢”。实测数据打脸——在千兆局域网内SSH 隧道的延迟比直连localhost高 8~12ms但比通过公网 DNS 解析再连接http://server-ip:8888低 180ms 以上。因为后者要经历 DNS 查询平均 50ms、TCP 三次握手30ms、TLS 握手100ms而 SSH 隧道复用已建立的连接仅增加加密/解密开销。真正影响体验的是带宽不是协议。如果你传的是 500MB 的.parquet文件瓶颈永远是磁盘 IO 和网络带宽不是 SSH。2.3 Ubuntu 20.04 的特殊适配点systemd、Python 版本与 locale 处理Ubuntu 20.04 是一个承上启下的 LTS 版本它默认使用systemd管理服务预装 Python 3.8且对中文支持存在历史遗留问题比如jupyter notebook 中文符号输入要输入两次这个热搜词就源于此。这些细节不处理会导致 Jupyter 启动失败或交互异常Python 版本冲突Ubuntu 20.04 自带python3指向/usr/bin/python3.8但很多深度学习库如 PyTorch 1.12要求 Python ≥3.9。若直接sudo apt install python3-pip再pip3 install jupyter装出来的 Jupyter 会绑定系统 Python 3.8导致后续conda create -n pytorch_env python3.9创建的环境无法被识别。正确做法是彻底隔离系统 Python 和科学计算环境。我们不碰/usr/bin/下的任何东西所有操作都在 conda 或 pyenv 管理的独立环境中进行。locale 编码问题Ubuntu 20.04 默认 locale 是C.UTF-8但某些中文输入法如搜狗输入法或 Jupyter 插件在非en_US.UTF-8下会触发编码错误。执行locale -a | grep en_US.utf8若无输出需运行sudo locale-gen en_US.UTF-8 sudo update-locale LANGen_US.UTF-8。这不是可选项是避免UnicodeDecodeError的必要前置。systemd 用户服务为实现“服务器重启后 Jupyter 自动拉起”不能简单写crontab -e加reboot因为 cron 环境缺少DISPLAY和 conda 初始化。正确姿势是创建 systemd user service~/.config/systemd/user/jupyter.service内容指定EnvironmentPATH/home/user/miniconda3/bin:/usr/local/bin:/usr/bin:/bin并启用systemctl --user daemon-reload systemctl --user enable jupyter.service。这个细节90% 的网上教程都漏掉了。3. 核心细节解析与实操要点从环境准备到隧道建立的每一步深挖3.1 环境准备为什么必须用 miniconda 而非 anaconda 或 apt 安装先明确结论在 Ubuntu 20.04 上部署 Jupyter首选 miniconda次选 pyenv坚决不用apt install python3-jupyter或anaconda全量包。理由如下apt install python3-jupyter安装的是 Ubuntu 官方源打包的版本截至 2024 年其jupyter-core版本仍为 4.6.32020 年发布而最新版已是 5.5.0。旧版本存在已知漏洞CVE-2022-21699且不支持 JupyterLab 4.x 的新特性。更重要的是它强制依赖系统 Python 3.8无法切换至 Python 3.9/3.10。anaconda全量包体积超 3GB包含 250 无需的科学计算库如 R、Julia、Qt Designer不仅浪费磁盘空间更会拖慢conda update速度。我在一台 16GB 内存的服务器上测试anaconda初始化后conda list命令平均耗时 4.2 秒而miniconda仅 0.8 秒。miniconda是精简版 conda 发行版仅含conda、python和少量核心包初始安装包仅 50MB。它让你从零开始构建环境完全掌控依赖树。执行wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh下载安装脚本后务必使用bash Miniconda3-latest-Linux-x86_64.sh -b -p $HOME/miniconda3参数静默安装-b表示 batch mode-p指定路径避免交互式安装污染$HOME/.bashrc。安装完成后必须执行三步初始化source $HOME/miniconda3/etc/profile.d/conda.sh—— 临时加载 conda 命令conda init bash—— 将 conda 初始化写入$HOME/.bashrcexec bash—— 重新加载 shell使conda activate生效注意不要运行conda update conda后立刻conda update --all。这会升级所有包到最新版可能引发兼容性问题如nbconvert7.0 与jupyter-core5.3 不兼容。我的经验是先conda create -n jupyter_env python3.9创建干净环境再在这个环境中pip install jupyterlab最后按需conda install pytorch torchvision torchaudio cpuonly -c pytorch。这样依赖清晰回滚成本低。3.2 Jupyter 配置文件生成与关键参数详解jupyter_notebook_config.py的 7 个生死参数Jupyter 的配置文件jupyter_notebook_config.py是整个远程访问的灵魂。它不在$HOME/.jupyter/下自动生成必须手动创建。执行jupyter notebook --generate-config后你会得到一个基础模板但以下 7 个参数必须手工修改缺一不可c.NotebookApp.ip localhost这是最关键的一行。它告诉 Jupyter“只监听本机回环地址别管外部网络”。很多人误设为0.0.0.0以为这样才能远程访问结果反而让 SSH 隧道失效——因为隧道转发的是localhost:8888如果 Jupyter 绑定0.0.0.0它会尝试监听所有接口但 Ubuntu 20.04 的net.ipv4.conf.all.route_localnet默认为 0导致localhost流量无法被正确路由。设为localhost是唯一安全且兼容隧道的值。c.NotebookApp.port 8888端口号可自定义但必须与 SSH 隧道-L参数一致。建议坚持用 8888避免记忆混乱。若需多实例可用 8889、8890 等但每个端口需单独建隧道。c.NotebookApp.open_browser False服务器无图形界面True会导致启动失败并报错No module named gi。这是新手最高频的报错来源。c.NotebookApp.allow_remote_access TrueUbuntu 20.04 的 Jupyter 6.0 版本默认为False即使你绑定了localhost也会拒绝来自非127.0.0.1的请求。SSH 隧道的流量源 IP 是127.0.0.1本地但 Jupyter 内部会检查X-Forwarded-For头设为True才允许隧道流量通过。c.NotebookApp.token 设为空字符串禁用 token 认证。因为 SSH 隧道本身已提供强认证密钥或密码再加 token 属于重复防御且 token 会出现在 URL 中有泄露风险。若坚持用 token必须配合c.NotebookApp.password usha1:...使用但复杂度陡增。c.NotebookApp.notebook_dir /home/user/notebooks显式指定工作目录。不设此项Jupyter 会以启动时的当前目录为根极易因路径错误导致文件找不到。建议创建专用目录mkdir -p ~/notebooks并赋权chmod 700 ~/notebooks。c.NotebookApp.disable_check_xsrf False必须为False默认值。设为True会禁用跨站请求伪造保护导致 notebook 无法保存、单元格无法执行。这是另一个高频静默故障点——页面看似正常但 CtrlS 无反应右键菜单灰色。配置文件修改后用jupyter notebook --config ~/.jupyter/jupyter_notebook_config.py启动观察终端输出是否含The Jupyter Notebook is running at: http://localhost:8888/。若出现Permission denied大概率是notebook_dir权限不足若卡在... is not a valid port检查port是否被其他进程占用sudo lsof -i :8888。3.3 SSH 隧道建立-L、-N、-f、-o四个参数的实战意义SSH 隧道命令ssh -L 8888:localhost:8888 userserver看似简单但每个参数都直指痛点。我们逐个拆解-L 8888:localhost:8888本地端口转发Local Port Forwarding。格式为-L [bind_address:]port:host:hostport。bind_address默认为localhost即只允许本机访问。如果你想让同一局域网的同事也能通过你的电脑访问不推荐生产环境可写成-L *:8888:localhost:8888但必须同步在服务器端sshd_config中设置GatewayPorts yes否则无效。-NNo command execution。告诉 SSH “只建隧道不执行远程命令”。没有它SSH 会登录后挂起一个 shell你关掉终端隧道就断了。加上-NSSH 进程纯粹作为隧道守护进程存在。-fForce background。让 SSH 在建立连接后自动转入后台运行。但注意-f必须与-N配合使用否则会报错backgrounding requires -N。实测中ssh -f -N -L 8888:localhost:8888 userserver执行后终端立即返回ps aux | grep ssh可见进程仍在。-oOption用于设置连接保活。最关键的两个是ServerAliveInterval 60—— 每 60 秒向服务器发一个空包防止中间 NAT 设备超时断连ServerAliveCountMax 3—— 连续 3 次无响应则断开连接避免僵尸进程。完整命令ssh -f -N -o ServerAliveInterval60 -o ServerAliveCountMax3 -L 8888:localhost:8888 userserver提示为免每次输密码必须配置 SSH 密钥。执行ssh-keygen -t ed25519 -C your_emailexample.com生成密钥对再ssh-copy-id userserver复制公钥到服务器。ssh-copy-id会自动将公钥追加到~/.ssh/authorized_keys并设置正确权限600。若手动复制请务必执行chmod 600 ~/.ssh/authorized_keys否则 SSH 会因权限过松而拒绝登录。4. 实操过程与核心环节实现从零开始的完整流水线4.1 第一步在 Ubuntu 20.04 服务器上搭建纯净 Jupyter 环境我们以一台全新安装的 Ubuntu 20.04 Server无桌面环境为例全程使用终端操作。假设服务器 IP 为192.168.1.100用户名为ubuntu。步骤 1系统更新与基础工具安装sudo apt update sudo apt upgrade -y sudo apt install -y curl wget git vim htop这一步确保系统组件最新避免curl版本过低导致 conda 下载失败。步骤 2安装 miniconda 并初始化cd /tmp curl -O https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh -b -p $HOME/miniconda3 rm Miniconda3-latest-Linux-x86_64.sh source $HOME/miniconda3/etc/profile.d/conda.sh conda init bash exec bash验证conda --version应输出24.x.xwhich conda应为/home/ubuntu/miniconda3/bin/conda。步骤 3创建 Python 3.9 环境并安装 Jupyterconda create -n jupyter_env python3.9 -y conda activate jupyter_env pip install --upgrade pip pip install jupyterlab注意此处用pip install而非conda install jupyterlab因为 conda 安装的 JupyterLab 版本较旧且依赖管理更重。pip安装更快版本更新及时。步骤 4生成并编辑配置文件jupyter notebook --generate-config vim ~/.jupyter/jupyter_notebook_config.py在文件末尾添加以下内容覆盖默认值c.NotebookApp.ip localhost c.NotebookApp.port 8888 c.NotebookApp.open_browser False c.NotebookApp.allow_remote_access True c.NotebookApp.token c.NotebookApp.notebook_dir /home/ubuntu/notebooks c.NotebookApp.disable_check_xsrf False创建 notebooks 目录mkdir -p ~/notebooks chmod 700 ~/notebooks。步骤 5启动 Jupyter 并验证本地访问conda activate jupyter_env jupyter notebook --config ~/.jupyter/jupyter_notebook_config.py此时终端应输出类似[I 10:23:45.123 LabApp] JupyterLab extension loaded from /home/ubuntu/miniconda3/envs/jupyter_env/lib/python3.9/site-packages/jupyterlab [I 10:23:45.123 LabApp] JupyterLab application directory is /home/ubuntu/miniconda3/envs/jupyter_env/share/jupyter/lab [I 10:23:45.124 ServerApp] jupyterlab | extension was successfully loaded. [I 10:23:45.124 ServerApp] Serving notebooks from local directory: /home/ubuntu/notebooks [I 10:23:45.124 ServerApp] Jupyter Server 2.7.0 is running at: [I 10:23:45.124 ServerApp] http://localhost:8888/lab [I 10:23:45.124 ServerApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).说明 Jupyter 已在localhost:8888正常运行。按CtrlC停止。4.2 第二步在本地机器Windows/macOS/Linux建立 SSH 隧道假设你的本地机器是 Windows 10/11使用 PowerShell 或 WSL2或是 macOS使用 Terminal。场景 AWindows PowerShell推荐 WSL2若你已安装 WSL2Ubuntu 20.04直接在 WSL2 终端中执行ssh -f -N -o ServerAliveInterval60 -o ServerAliveCountMax3 -L 8888:localhost:8888 ubuntu192.168.1.100若用 PowerShell 原生命令需先确保 OpenSSH Client 已启用设置 → 应用 → 可选功能 → 添加 OpenSSH 客户端。命令相同。场景 BmacOS 或 Linux 本地机终端中执行ssh -f -N -o ServerAliveInterval60 -o ServerAliveCountMax3 -L 8888:localhost:8888 ubuntu192.168.1.100验证隧道是否建立lsof -i :8888应显示ssh进程监听localhost:8888。场景 CVS Code 远程开发集成vscode连接ssh远程服务器这是进阶用法。在 VS Code 中安装 “Remote - SSH” 插件点击左下角绿色按钮 “Connect to Host...” 输入ubuntu192.168.1.100。连接成功后按CtrlShiftP打开命令面板输入 “Jupyter: Create New Blank Notebook”VS Code 会自动在远程服务器上启动 Jupyter 内核并在本地渲染 notebook 界面。这种方式无需手动建隧道但底层仍是 SSH 隧道机制且支持jupyter notebook怎么分享中的“Share”按钮生成临时链接。4.3 第三步浏览器访问与首次使用调试隧道建立后在本地浏览器中打开http://localhost:8888/labJupyterLab或http://localhost:8888/tree经典 notebook。你应该看到熟悉的 Jupyter 界面。首次访问必做三件事检查 kernel 状态右上角应显示 “Python 3” 且为绿色圆点。若为灰色点击右侧三角形 “Change kernel” 选择Python 3 (jupyter_env)。这一步确认 conda 环境被正确识别。测试中文输入新建 notebook输入print(你好世界)按CtrlEnter。若输出乱码说明 locale 未生效回服务器执行export LANGen_US.UTF-8并重启 Jupyter。验证文件读写在~/notebooks下创建test.ipynb写入代码并保存。关闭浏览器重新打开http://localhost:8888/tree确认文件存在且内容未丢失。实操心得我曾遇到一次诡异问题——隧道能连页面能打开但所有单元格执行都返回Kernel died, restarting。排查发现是服务器内存不足free -h显示仅剩 200MBJupyter 启动 kernel 时被 OOM Killer 杀掉。解决方案sudo sysctl vm.swappiness10降低交换倾向并在~/.jupyter/jupyter_notebook_config.py中添加c.NotebookApp.max_buffer_size 536870912512MB限制内存缓存。这个细节只有在真实服务器上跑过大 notebook 才会踩到。5. 常见问题与排查技巧实录从Connection refused到Reset by peer的全链路诊断5.1 隧道连接类问题ssh: connect to host ... port 22: Connection refused这表示本地机器根本连不上服务器的 SSH 端口。原因及对策现象可能原因排查命令解决方案Connection refused服务器 SSH 服务未运行ssh -v ubuntu192.168.1.100加-v显示详细日志sudo systemctl start ssh启动服务No route to host网络不通防火墙、网线、IP 错误ping 192.168.1.100检查服务器是否在同一局域网ifconfig确认 IPssh: Could not resolve hostname d: Name or service not known主机名d无法解析nslookup d改用 IP 地址或在本地/etc/hosts添加192.168.1.100 d注意Ubuntu 20.04 默认禁用 root SSH 登录。若你用rootserver连接失败是正常现象。应使用普通用户如ubuntu登录再用sudo su -切换。5.2 Jupyter 启动类问题The port 8888 is already in use端口被占是第二高频问题。sudo lsof -i :8888输出可能为jupyter进程说明上次 Jupyter 未正常退出kill -9 PID即可。code进程VS Code Remote-SSH 插件占用了该端口。改用ssh -L 8889:localhost:8888并访问http://localhost:8889。node进程其他 Web 服务如本地开发服务器占用了 8888。统一改用8889避免冲突。5.3 隧道转发类问题channel 3: open failed: connect failed: Connection refused这是隧道已建立但无法将流量转发到远端localhost:8888的典型错误。原因一定是 Jupyter 未在服务器上运行或运行端口与隧道不匹配。执行# 在服务器上检查 Jupyter 是否监听 8888 sudo ss -tuln | grep :8888 # 应输出tcp LISTEN 0 128 *:8888 *:* users:((jupyter-noteboo,pid12345,fd7)) # 若无输出说明 Jupyter 未启动 # 若输出为 :::8888IPv6而隧道是 IPv4需在配置中加 c.NotebookApp.allow_origin *5.4 浏览器访问类问题页面空白、kernel connecting、404 Not Found现象日志线索根本原因修复动作页面空白控制台报Failed to load resource: net::ERR_CONNECTION_REFUSED浏览器开发者工具 Network 标签页本地 8888 端口无监听进程lsof -i :8888检查 SSH 隧道进程是否存在kernel status 长期 “connecting”Jupyter 终端无新日志c.NotebookApp.allow_remote_access False或c.NotebookApp.disable_check_xsrf True修改配置文件重启 Jupyter访问http://localhost:8888/tree返回 404但http://localhost:8888/lab正常URL 路径差异JupyterLab 为默认首页经典 notebook 需显式访问/tree直接访问/lab或在配置中设c.NotebookApp.default_url /tree5.5 高级排障ssh connection reset by peer与长连接保活Reset by peer通常发生在网络不稳定时如 WiFi 切换、VPN 断连。SSH 连接被对端主动关闭。对策是强化保活机制服务器端加固编辑/etc/ssh/sshd_config添加ClientAliveInterval 60 ClientAliveCountMax 3然后sudo systemctl restart sshd。客户端脚本化重连写一个jupyter-tunnel.sh脚本#!/bin/bash while true; do ssh -f -N -o ServerAliveInterval60 -o ServerAliveCountMax3 -L 8888:localhost:8888 ubuntu192.168.1.100 if [ $? -eq 0 ]; then echo Tunnel established break else echo Tunnel failed, retrying in 5s... sleep 5 fi done赋予执行权限chmod x jupyter-tunnel.sh运行./jupyter-tunnel.sh。它会在隧道断开后自动重试直到成功。终极方案autosshsudo apt install autossh然后autossh -M 0 -f -N -o ServerAliveInterval60 -o ServerAliveCountMax3 -L 8888:localhost:8888 ubuntu192.168.1.100。autossh会监控 SSH 进程崩溃后自动拉起比手动脚本更可靠。6. 进阶扩展与生产级实践从单机隧道到多用户协作环境6.1 多端口隧道同时访问 Jupyter、TensorBoard 与 VS Code Server一个 SSH 连接可建立多个隧道。例如你还需要在服务器上跑 TensorBoard端口 6006和 VS Code Server端口 8080ssh -f -N \ -o ServerAliveInterval60 \ -o ServerAliveCountMax3 \ -L 8888:localhost:8888 \ -L 6006:localhost:6006 \ -L 8080:localhost:8080 \ ubuntu192.168.1.100然后在本地浏览器分别访问http://