汇总不同场景下的远程连接方法、代理服务等;探索更多远程开发方式。

①前两节主要讲解了如何用ssh实现两主机的互访;
②第三节讲了如何通过代理访问外网资源;
③第四节介绍了当我们只专注与远程生产场景下的,更高效便捷的访问方式——code CLI。

非特殊说明, 下述客户端指代主访主机, 服务端指代被访主机。
下述所涉Windows场景下的命令执行, 一律默认用powershell.

0. 基础知识

端口转发

跳转

代理

  • 正向代理(Forward Proxy):隐藏客户端IP和身份
    客户端(通常是用户)通过正向代理服务器来访问其他服务器的资源。
    用途:通常用于增加访问控制和隐私,绕过访问限制,或提供匿名访问。
  • 反向代理(Reverse Proxy):隐藏服务器IP和身份
    反向代理服务器接收客户端请求,并将请求转发给内部服务器(后端服务器)。
    用途:用于负载均衡、安全性、缓存,以及隐藏后端服务器的实际结构。

1-用ssh实现远程访问

这里客户端是你正在操作的主机, 它最好能打开一个终端窗口 (e.g. cmd, powershell, bash…); 服务端是将被访问的远程主机, 它可以Windows, wsl, Ubuntu, macOS… .

在此类方法中, 客户端和服务端通过ssh协议进行通信, 根据使用场景的不同, 构建ssh连接的复杂性也有所不同。

1-1-ssh工具使用前提

服务端已安装openssh-server

windows安装openssh-server

你可以把Windows作为服务端, 但别用它来搞生产.

管理员身份
# 安装软件
# 检验是否安装
# - 没有则执行安装( 也可进入`系统设置→ 添加可选功能→ OpenSSH服务器`点击安装)
# - 安装了则检验`sshd服务`的状态
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0154
Get-Service sshd

# 开启服务 (也可进入`系统搜索→ 服务→ OpenSSH服务器`右键开启)
# 设置服务开机自启 (同上)
# 确保 Windows 防火墙允许 SSH 连接, 默认22.
Start-Service sshd
Set-Service -Name sshd -StartupType Automatic
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22

# 然后重启powershell终端.
# 最后验证本机是有效的`ssh服务端`
ssh -p 22 user@127.0.0.1
ssh localhost

ssh相关的权限问题非常严格, 若有报错, 请参考下面

WSL或其他Linux
  1. 安装ssh-server: sudo apt-get install -y openssh-server
  2. 生成主机秘钥(/etc/ssh/): sudo ssh-keygen -A

    非常必要, 用于别人连接本机时, 别人生成的known_hosts条目.

  3. 设置服务开机自启: sudo systemctl enable ssh. 如果失败则用sudo service ssh enable
  4. 启动/重启: sudo systemctl restart ssh
  5. 测试: ssh -p 2222 localhost. 如果有报错, 尝试添加参数-o StrictHostKeyChecking=no -o ConnectTimeout=5
云服务器

一般来说, 云服上默认是安装了ssh服务器的.

服务端已按需修改了配置

服务端的配置文件的路径:

  • Windows: (管理员)notepad C:\ProgramData\ssh\sshd_config
  • Linux: sudo vim /etc/ssh/sshd_config
常见的一些配置
# 必做:
# 1. 默认端口22. 如果是wsl1要修改,为了不与windows冲突; 而wsl2可不必修改, 因为它已是一台独立主机
# 2-3. 允许秘钥、不允许密码验证登录(密钥永远比密码安全)
# 4. 不允许root远程登录(安全起见)
Port 2222
PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin no
# 选做
GSSAPIAuthentication yes # 解决一台服务器管理多个ssh服务
UseDNS no # 加快响应速度因为在内网环境下
ListenAddress 192.168.25.130 # 只监听指定内网的IP
Match User anoncvs # 当前环境允许登录的用户
GatewayPorts yes
## 用于远程端口转发 (跳板机中使用)
GatewayPorts yes
AllowTcpForwarding yes
PermitTunnel yes
......

修改后,

  • 检查配置文件的语法: sudo sshd -t
  • 重启sshd:
    (wsl)sudo service ssh restart
    (linux)sudo systemctl restart ssh
    (powershell)Restart-Service sshd

已准备好1-2对秘钥对

详见

1-2-连接常见问题排查

常见

连接出问题,先尝试删除客户端~/.ssh/know_hosts*,
再尝试在服务端重启sshd服务.

Windows下启动sshd服务失败

  • 问题: 明明已经在系统设置→ 添加可选功能中安装了openssh-server,
    • 但在powershell执行Get-Service或Start-Service sshd时总报错找不到sshd服务.
    • 或搜索进入服务, 点击启动OpenSSH Server, 总报错1067: 进程意外终止.
  • 原因: 根据博主的经验, 是此前残余的ssh相关目录没有删干净.
  • 解决:
    • 先进入系统设置→ 添加可选功能, 点击卸载openssh-server
      (或powershell: Remove-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0)
    • ⭐ ⭐ 删除C:\Users\用户名\.sshC:\ProgramData\ssh.
    • 如果系统要求重启, 则重启.
    • 重新安装openssh-server.

权限问题造成报错

⚠️ ⚠️ ⚠️ 大多数连接失败都是出自该类原因.

出于安全考虑, .ssh下的目录和文件的权限设置非常严格, 直接影响SSH的正常工作。请检查以下内容:

  • 整个~/.ssh/目录树的所有者必须是当前用户;

  • [bash] 中操作时,

    • $HOME权限应为755
    • .ssh/权限应为700;
    • 私钥authorized_keysconfig600;
    • 公钥known_hosts644.
  • [powershell] 中操作时,

    • .ssh\只对当前用户可读与执行;
    • 私钥authorized_keysconfig只对当前用户可读;

    修改权限的powershell命令: (管理员身份)

    # 设置 .ssh 目录的权限
    icacls "C:\Users\ray3060\.ssh" /inheritance:r
    icacls "C:\Users\ray3060\.ssh" /grant:r "ray3060:(OI)(CI)(RX)"
    # 设置 config 文件的权限
    icacls "C:\Users\ray3060\.ssh\config" /inheritance:r
    icacls "C:\Users\ray3060\.ssh\config" /grant:r "ray3060:(R)"
    # 设置密钥文件的权限
    icacls "C:\Users\ray3060\.ssh\ray3060_to_jumper_rsa" /inheritance:r
    icacls "C:\Users\ray3060\.ssh\ray3060_to_jumper_rsa" /grant:r "ray3060:(R)"

    然后重启PowerShell 窗口, 再执行相关命令, 不再报错.

ssh登入Windows后无法使用wsl命令

  • 问题: 非远程连接时, 在Windows终端执行wsl --version等命令, 正常;
    但ssh远程连接后, 再执行wsl相关命令就会报错系统无法访问此文件.
  • 原因: 不详, 但wsl开发团队有招儿.
  • 解决: 参考, 重装wsl版本即可: wsl --update --pre-release.

    如果速度太慢, 可手动下载.

1-3-场景1-服务端可直访

当服务端是内网的其他主机云服务器时, 可以直接用ssh连接.

  • 先把公钥发给服务端: 详见
  • 然后连接: ssh -p 2222 user@remote_host -i ~/.ssh/id_rsa

如果想简化连接命令(ssh test), 需在客户端的~/.ssh/config中添加一些配置, 如:

Host test
HostName server-IP_or_url
User server-USER
Port 2222
ServerAliveInterval 60
IdentityFile ~/.ssh/id_rsa

1-4-场景2-服务端不可直访with跳板机

此法也被称为: 远程端口转发/内网穿透/反向代理

通常我们想连接的服务端都在某一个内网中, 如公司服务器、工位上的电脑、云服务器里的docker实例…… 它们的特点是:

  • 这些主机本身是可以访问互联网的;
  • 它们由于缺少公网IP、防火墙、安全策略等原因, 无法直接被访问。

这样我们可以准备一台有公网IP的跳板机, 跳板机可以在任何位置, 一般买个云服务器就搞定了.

远程端口转发的核心

A 👉 B 👉 C

服务端C的ssh端口与跳板机B端口p建立映射, 让客户端A以为:
ssh连到跳板机的端口p, 就是连到服务端的ssh端口. 这就实现了穿透.

step1-准备两对密钥

谁主动连接, 谁生成秘钥对.
ssh-keygen -t rsa -b 4096 -C "[email protected]" -f ~/.ssh/a_to_b_rsa

  • KEY-sj: 用于服务端(pri-key)→ 跳板机(pub-key)的连接, c_to_b_rsa & pub
  • KEY-cs: 用于客户端(pri-key)→ 服务端(pub-key)的连接, a_to_c_rsa & pub

权限问题造成报错请参考上面.

step2-配置跳板机

  • 防火墙设置
    如果你的跳板机是云服务器, 进入相应控制台的安全组, 在入站策略中开启任一闲置端口(如18086)并重启云服。

    ⚠️ 该端口用以映射到服务端的ssh端口, 让客户端以为连到该端口, 就等于连到了服务端的ssh服务。
    ⚠️ 一般地, 云服务器设置了安全组, 就无需在云服命令行上设置防火墙.

  • sshd配置
    在你想连接的远程主机眼里, 跳板机就是ssh服务端, 因此需配置其sshd().

    注意: GatewayPortsAllowTcpForwarding必须设置为yes.

  • 密钥配置
    KEY-sj的公钥内容追加到跳板机~/.ssh/authorized_keys文件,没有该文件则创建.

step3-配置服务端主机

先处理密钥

KEY-sj的私钥文件应存在于~/.ssh/
KEY-cs的公钥内容应追加到~/.ssh/authorized_keys文件, 没有则创建;

权限问题造成报错时请参考上面.

后添加跳板机信息
~/.ssh/config
Host jumper
HostName 跳板机IP
Port 跳板机ssh端口
User 跳板机用户名
ServerAliveInterval 60
IdentityFile ~/.ssh/刚才KEY-sj的私钥
后执行远程转发命令

ssh -gfnNTR 18089:localhost:22 jumper

  • 解释: g开启网关转发, f放入后台, n不接受输入, N不开交互式shell, T禁用伪终端, R代表这是远程的转发规则。
  • 该命令将本机(服务端)的22端口映射到了跳板机的18086端口, 使得外界访问本机的ssh服务变为可能。
  • 该命令长期在服务端后台执行, 可通过ps aux | grep ssh命令查看其进程

step4-客户端主机

直接执行: ssh 服务端用户名@跳板机IP -p 18087 -i KEY-cs的私钥

上述命令也可改到~/.ssh/config中。

1-5-场景3-服务端不可直访+第三方内网穿透工具

自己实现端口转发, 需要购买云服, 有成本. 或者你还可以选择很多公司免费的内网穿透工具.

可视化工具-花生壳

使用场景: 服务端有桌面系统, 如工位上的windows, 花生壳需安装于服务端.

使用方法: 直接添加一个端口映射项目即可, 可最终得到命令形如ssh -p 21570 [email protected]来连接服务端.

优点: 足够简单

缺点: 花生壳定义到wsl的映射时, 需面临一个情况, 即宿主机每次开关机都会重启虚拟网络适配器导致wsl的内网IP改变, 进而需要重新设置映射, 不够方便。

工具-ZeroTier

ZeroTier, 有待研究.
功能:创建一个虚拟局域网,实现多台机器的互访。

命令行工具集合

多种工具, 这些工具不仅限于tcp协议, 有待探索.

命令行工具-bore

优缺点: 简单, 但是bore.pub带宽超低。

公网跳板机(可选): 将该主机作为bore服务器, 相当于跳板机: bore server

服务端:

  • 在想要暴露端口的主机上下载二进制可执行文件
  • 暴露本地端口: bore local 22 --to bore.pub
  • 如果设置了公网主机, 命令改为 bore local 22 --to 公网主机IP
  • 你会得到一个新端口newP

客户端:

  • 访问暴露的端口: ssh -p newP 服务端用户名@bore.pub

1-6-场景4-服务端不可直访+CloudFlare

参考资料: 视频博主教程, CF实现SSH官方教程

Cloudflare-tunnel 可以帮助个人用户对内网服务的免费访问, 可以是https服务SSH服务SMB服务… 这里只介绍SSH服务.

优缺点

优点: 相当于一个免费的公网跳板机, 纯白嫖, 不再自己准备有公网IP的服务器, 香不香?

缺点: 远程操控主机时, 响应会比较卡顿, 特别是在使用终端时, 非常影响心情, 这是因为CF服务器在海外.

方法概述

‘官方教程’里有两种实现SSH穿透连接的方法: Cloudflare WARPcloudflared access, 这里只介绍后者.

⚠️tips: 该方法中, SSH服务器、SSH客户端都要安装connector并作一些配置.
⚠️premise: 备好一对SSH密钥.
前三步可以在任意一台机器上的浏览器中操作.

  1. 域名迁移 : 将自己的域名托管到CF, 即把域名的NS服务器换成CF指定的.

  2. 开启Zero Trust模块 : 进入CF控制台左侧Zero Trust模块 👉 给自己的ZT起个名字, 格式如{name}.cloudflareaccess.com 👉 选择免费的套餐 👉 此时会让你添加付款方式, 不管它 👉 直接回到CF控制台 👉 重入ZT模块, 直接呈现ZT控制台了.

  3. 创建Tunnel : 进入ZT控制台左侧Networks模块 👉 Tunnels 👉 Add a tunnel 👉 选择CloudFlared的type 👉 给tunnel命名然后save

  4. 服务端连接到CF : (这里介绍可视化方法)
    浏览器登录CF 👉 ZT 👉 Networks>Tunnels 👉 你刚才创建的tunnel, 右边三点下拉菜单, 点击configure 👉

    • Overview页面: 按照提示选择系统、安装并运行cloudflared;
    • Public Hostname页面: 选择Domain, 设置一个Subdomain, Type选择SSH, URL输入localhost:2222, 其他配置可选, 最后保存.

      ⚠️ 如果你是在非服务器主机上操作这个步骤, localhost就要改成服务器主机IP;
      端口号一般是22, 具体看你服务端的sshd配置.

      cloudflare-tunnel配置服务端

    另外, 把你准备好的密钥对的公钥存入服务器的~/.ssh/authorized_keys文件.

  5. 客户端连接到CF :

    • 仅安装cloudflared(安装包). 注意这里不要执行刚才Overview页面的运行命令, 因为这是客户端嘛;
    • 配置远程连接信息:
      "~/.ssh/config"
      Host luge-wsl
      HostName luge-wsl.taddream.site
      User james
      IdentityFile ~/.ssh/reach-luge-wsl-rsa
      ProxyCommand "C:\Program Files (x86)\cloudflared\cloudflared.exe" access ssh --hostname %h

      其中, luge-wsl是自定义的连接别名;
      HostName是你在”CF>ZT>Networks>Tunnels>{your_tunnel}>Public Hostname”中设置的三级域名;
      User是你将要远程登录的服务器的用户名;
      IdentityFile是你准备的密钥对中的私钥;
      ProxyCommandcloudflared的命令, 把cloudflared.exe的路径改成你自己的.

  6. 测试 : 客户端执行ssh luge-wsl, 你能登录到服务器了.

1-7-服务端IP不固定时

场景:本地想访问工位的wsl

问题产生:Windows是通过虚拟交换机给Win10主机与WSL2子系统分别分配IP地址,当Windows重启并再次打开WSL2时,虚拟交换机会被重新创建,分配给它们的IP地址也会随着改变。

常规解决思路:每次重启后都需要用新的ws内网IP来再次执行(#1.4-#1.6)的步骤.

讨巧解决思路:直接访问win端系统,在进入cmd时系统自动跳转到bash.exe(就像Linux中在.bashrc末尾加上zsh一样)

  • 方法:执行跳转命令
    New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\WINDOWS\System32\bash.exe" -PropertyType String -Force
  • 然后再通过(#1.4-#1.6)的方法访问工位的Windows.

2-搭梯子

只想访问特定的外部网站

场景:我国内的服务器需要从github下载文件, 为此只想实现访问github域名的能力

下述方法综述

法1~法4我多次尝试,有的有时有效,有的完全无效;只要自己有梯子,法5一定能行;法6属于是曲线救国了,保底方案。

法1:修改本地hosts文件

更新:查到的IP地址国内也不一定能访问,此法无效。

  • 原理:我国通过一些技术手段实现了DNS污染,返回错误的GitHub的ip地址。因此我们只需更改/增添hosts中的域名IP映射即可
  • 获取正确映射:进入网站 查询(如 github.com -> 20.205.243.166)
  • 在Windows:
    修改C:\Windows\System32\drivers\etc\hosts权限,
    后进入添加映射(如 20.205.243.166 github.com),
    刷新本地DNS缓存:ipconfig /flushdns
  • 在Linux:
    只需在/etc/hosts添加映射即可
    若未生效,sudo systemctl restart nscd,如报错则须安装:sudo apt install nscd sudo /etc/init.d/nscd restart

法2:修改DNS

  • 原理:不同的DNS服务商可能有不同的解析方法
  • 在Linux:sudo vim /etc/resolv.conf添加/修改nameserver ,指定你想要使用的DNS服务器的IP地址,后执行sudo systemctl restart systemd-resolved生效

    如:nameserver 114.114.114.114 nameserver 223.5.5.5

法3:借助github520项目

原理仍是修改hosts

法4:针对github网站可用ssh密钥对

  • 准备一对密钥
  • 然后把公钥复制到github: “Settings” -> “SSH and GPG keys” -> “New SSH key”
  • 然后验证你的主机和github的连通性:
    ssh -T [email protected] -i ~/.ssh/id-rsa
    # 返回:“Hi JamesRay0713! You've successfully authenticated”, 则说明成功。
    # 若加上 -v 参数,会打印详细的连接信息
  • 此时就可以用ssh下载仓库了:git clone [email protected]:your-username/your-repository.git

法5:配置代理

假设我们已经通过一些渠道得到了一个梯子,且正运行在本地,那请移步系统的设置→ 网络→ 代理→ 手动设置代理获取代理地址和端口(e.g. 127.0.0.1:7890
然后在终端给git配置代理服务器:git config --global http.proxy http://127.0.0.1:7890
可验证查看配置成功:git config --global --list

法6:借助gitee

以上方法均无效时,老实把目标仓库导入到gitee,然后使用gitee仓库链接。

用于所有外网的梯子概述

实现科学上网有多种方法, VPN(虚拟专用网络), proxy(代理服务), ssh…
科学上网方法导图

梯子-ssh大法__国外云服

ssh一般用于远程服务器的登录, 但是ssh还有一个很强大的功能, 就是端口转发. 通过端口转发, 我们可以实现本地网络流量的转发, 从而实现科学上网. 该方法实际上也是proxy的一种.

具体方法:

  1. 自行购买一个国外的云服务器(CVM), 拿到它的公网IP(cvm-ip). 此时你本地ssh可正常登录cvm-ip.

  2. 在本地执行端口转发命令, 形如:
    ssh -D 1080 -qCNf -p 22 user@cvm-ip -i ~/.ssh/id_rsa

    命令的解释:
    D是动态转发, SSH客户端(本地)将创建一个SOCKS5代理服务器, 端口为1080, 该代理服务器会将所有传入的流量转发到通过SSH连接的远程主机上。
    q是静默, C是压缩, N是不执行远程命令, f是后台运行.
    i是私钥路径.

  3. 在本地系统设置的代理服务器中把地址127.0.0.1:1080放进去.

  4. Bingo!

可能会出现的BUG:
连接后会时不时地失效,在本地重新ssh -D就好了。这样次数多了, CVM端会累积过多的ssh进程,记得手动杀一杀.

优缺点:
由于是你自己的云服务器, 因此很稳定. 但是国外云服务器的价格较高.

梯子-proxy方法

ssh方法是依赖端口转发功能, 实现自动创建代理服务器. proxy方法则是你主动获取代理服务器及其端口, 有两种获取的方法: 直接花钱购买的、自己动手搭建的. 另外也有很多流行的代理工具来管理代理服务器, 并实现了更多的功能.

详见

梯子-wsl中

wsl作为windows下的虚拟机, 可以直接使用宿主机的代理服务, 而无需单独去搭建代理. 前提是你的宿主机已经配置好了代理服务, 且wsl可以访问宿主机网络.
具体方法为:

  1. windows利用代理工具(e.g. clash, v2ray)开启了代理服务, 且开启了允许局域网设备连接.
  2. 拿到windows的IP(注意, 是’vthernet(WSL)’网络适配器下的IP), 以及代理工具中设定的代理端口.
  3. 在wsl中设置代理:
    ~/.bashrc
    export http_proxy=http://windows-ip:代理端口
    export https_proxy=http://windows-ip:代理端口
  4. bingo!
  5. 或者你也可以在特定的应用程序中以参数的方式使用代理url, 如gitcurlwget等.

3-VScode相关的远程开发工具

vscode有丰富的插件和强大的远程连接功能:

  • 官方插件Remote SSH: 把SSH的使用集成到了vscode中;
  • 官方插件Remote Tunnels: 允许你从任何设备安全地连接到运行VS Code的远程机器,而无需直接暴露该机器到公网。如果不考虑国内网络环境造成的延迟, 它比端口转发更能打.
  • 官方插件Docker: 深度集成docker所有功能, 本地、远程的docker容器都没问题.
  • 其他相关工具code-server: 专为浏览器设计的vscode.

Remote-Tunnels

(GWF原因, 不推荐.)

中文microsoft文档

⚠️⚠️ 2024/07/31发现:

  • 服务端需要配置代理, vscode-cli的code tunnel命令才跑得起来;
  • 客户端也要配置代理, vscode的Remote-tunnel扩展才能识别到账号下的tunnel. 不是说你系统挂上了梯子就行了, 而是在vscode的settings里搜索Http: Proxy (Applies to all profiles), 在它里面写入http://127.0.0.1:{梯子端口号}才行.

简介

本质是vscode客户端与服务端的通信。在服务端主机已经安装好code cli且运行了tunnel命令的前提下,我们可直接访问URL连接到远端.

优点:

  • 使用端到端加密,无需开放防火墙端口公网IP;
  • 在移动设备上也能访问完整的开发环境, 毕竟是web;
  • 方便教师共享开发环境给学生或设置统一的培训环境.

缺点: ⚠️⚠️ 国内的延迟不小呢, ⚠️⚠️ , 原因是VS Code Tunnel 本身托管在 Visual Studio 的云服务中, 而这个云服务器在国外.

配置step1-远程服务端

先安装VSCode-CLI

资源所有版本

  • 方法1(推荐): snap安装
    sudo snap install code --classic

  • 方法2:
    去网页下载压缩包, 认准系统和架构,如下图. 然后存入服务端, 解压

  • 方法3: 命令方式

    # 针对不同的系统和架构, 请修改下面的`cli-alpine-x64`
    curl -Lk 'https://code.visualstudio.com/sha/download?build=stable&os=cli-alpine-x64' --output vscode_cli.tar.gz
    tar -xf vscode_cli.tar.gz

最终我们都会得到一个名为code的文件.

后开通tunnel

①用命令创建隧道:./code tunnel,将得到绑定到此远程计算机的 vscode.dev URL。若是首次创建,
②则需按提示选择登录账户(建议Microsoft)、
③进入devicelogin的url,登录账户,输入它给你的验证码、
④给这台远程机器命名。
⑤获得vscode dev的URL

为了确保tunnel持久运行, :

code tunnel service install        # 方法1: 把这个进程变成服务. 换成`uninstall`是卸载服务.
code tunnel --no-sleep # 方法2: 执行命令时添加`不睡觉`参数.

配置step2-本地客户端

  • 方法1:在本地网页上开发。直接打开 URL即可进入网页版vscode desktop

    若是首次打开URL,会提示登录GitHub/Microsoft账户来授权你能正确地访问隧道。(国内没有梯子的用户建议使用Microsoft账户)

  • 方法2:用本地VScode Desktop开发。先安装插件Remote SSHRemote Tunnels;后进入左侧面板的Remote,点击Tunnels右侧的+,选择账户,系统会自动刷出你账户下的远程机器名,连接即可。

code-server

coder家的code-server是一个开源的、基于浏览器的、基于vscode的代码编辑器。号称可以用浏览器访问运行在任何地方的vscode.

code-server在在本地运行, 无延迟, 强烈推荐!
code-server集成了code的全部功能, 因此无需提前安装命令行版的code.

安装与启动code-server

curl -fsSL https://code-server.dev/install.sh | sh
tee $HOME/.config/code-server/config.yaml <<EOF
bind-addr: 127.0.0.1:8080
auth: password
password: $your_password
log: info
EOF
sudo systemctl enable --now code-server@$USER # 启动和开机自启

本机的code-server运行后, 你可在本地浏览器用http://127.0.0.1:8080访问vscode-web了, 登录密码是上面config.yaml中的your_password.

如果你还想在局域网外的其他机器上安全访问本机, 那么:

  • 首先本机要有公网IP, 或者本机的8080端口已经通过远程端口转发映射到了公网主机的指定端口上;
  • 然后针对端口的暴露, 要有安全措施. 官方教程给出了4种安全操作和暴露code-server的方法:
    • 方法1, 在其他机器上使用SSH本地端口转发:
      • 先在本机的code-server的config.yaml里修改auth为auth: none;
      • 重启code-server服务: sudo systemctl restart code-server@$USER;
      • 其他机器上使用本地转发命令: ssh -NL 8080:127.0.0.1:18080 user@公网ip;
      • 最后, 在其他机器上打开URL即可.

        优点: 本机的防火墙不必放开8080端口, 即没有暴露的风险.
        缺点: 其他机器是手机, ipad等设备时, 是没有ssh功能的.

    • 方法2, 使用CaddyLet's Encrypt功能.

      优点: 可以有HTTPS了, 且还可设置用户名+ 密码.
      缺点: 得准备域名绑定到本机的(或本机映射的)公网IP.

    • 方法3, 使用NginxLet's Encrypt功能.
    • 方法4, 使用自签名证书. 不推荐.
    • 方法5, 直接暴露, 不带安全措施, 只用password. 可以这样, 但不推荐.

根据我的实际需求, 我很想要在任何设备的浏览器上都能访问到vscode-web. 因此, 我倾向于使用方法2, 下面将介绍后续的配置步骤.

借助Caddy的code-server配置

其大体思路是, 用自己的域名做反代, 使得所有的外部访问都能路由到code-server的本地端口.

步骤如下:

  1. 确保本机放开了HTTP(port 80)和HTTPS(port 443)的防火墙规则.
  2. 确保你域名的DNS解析里含有指向本机公网IP的A记录.
  3. 安装Caddy:
    https_proxy=http://127.0.0.1:7890
    sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
    curl -x "$http_proxy" -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
    | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
    curl -x "$http_proxy" -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
    | sudo tee /etc/apt/sources.list.d/caddy-stable.list
    sudo apt update
    sudo DEBIAN_FRONTEND=noninteractive apt-get install -y caddy
  4. 配置Caddy: 执行sudo vim /etc/caddy/Caddyfile, 写入以下内容
    mydomain.com {
    reverse_proxy 127.0.0.1:8080 }
  5. 重启Caddy: sudo systemctl restart caddy.
  6. 访问https://mydomain.com即可进入vscode-web.

Caddy的另一种安装配置-CF插件

TODO: http+ip+port的模式不够安全, 需要用Caddy对自己的域名做反代. 但此前配置时被卡在’域名未备案’的问题上.

# 10-1 (helper func) 安装配置caddy
install_caddy() {
echo "✨ ✨ INSTALLING: Caddy... ✨ ✨"
if sys_ctl status caddy | grep -q "(running)"; then
echo " ✅ caddy already running." && return 0
fi
# 安装go
# sudo apt-get install -y golang-go # 不行, 安装后的版本是1.18
sudo snap install go --classic # 可行, 得到go-v1.23
# 安装xcaddy
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
export PATH=$PATH:$HOME/go/bin
if ! grep -q "/go/bin" "$HOME/.zshrc"; then
echo -e "\nexport PATH=$PATH:$HOME/go/bin" >> "$HOME/.zshrc"
fi
# 构建带cloudflare插件的caddy
xcaddy build --with github.com/caddy-dns/cloudflare
sudo mv ./caddy /usr/bin/caddy
# 把CF的API-token写入环境变量
export CLOUDFLARE_API_TOKEN="$CF_dns_api_token"
if ! grep -q "CLOUDFLARE_API_TOKEN" "$HOME/.zshrc"; then
echo -e "\nexport CLOUDFLARE_API_TOKEN=$CF_dns_api_token" >> "$HOME/.zshrc"
fi
# 配置Caddyfile: 绑定域名进行反代; 指定CF的ssl证书
local f_caddy="/etc/caddy/Caddyfile"
sudo cp "$f_caddy" "$f_caddy.bak" || true
sudo tee "$f_caddy" << EOF
cs.taddream.site {
reverse_proxy 127.0.0.1:8080
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
}
}
EOF
# 开启Caddy服务
sudo tee "/etc/systemd/system/caddy.service" << EOF
[Unit]
Description=Caddy web server
Documentation=https://caddyserver.com/docs/
After=network.target

[Service]
User=root
Group=root
ExecStart=$(which caddy) run --environ --config $f_caddy
ExecReload=$(which caddy) reload --config $f_caddy
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF
sys_ctl restart caddy
if sys_ctl status caddy | grep -q "(running)"; then
echo " ✅ caddy running."
fi
}

Static Badge Static Badge Static Badge Static Badge
Copyright © 2023-2024 Raymond H., All Rights Reserved.