出于安全或性能等原因,开发环境被部署在了内网云环境中,内网云环境与外网完全隔离,且所有的开发环境资源(如数据库、Redis等)只能通过内网云环境访问,本地物理机无法直接访问这些测试资源,只能通过RDP协议间接访问内网云环境中的桌面,这给开发工作带来了极大的不便。为了能够直接在本地物理机进行开发,接下来将介绍4种远程开发的方法:
- 使用nginx反向代理持续暴露远程资源
- 使用ssh转发持续访问远程资源
- 使用Microsoft的Visual-Studio-Code远程开发工具
- 使用Jetbrains的Gateway远程开发工具
本文中的远程开发指的是:通过本机访问远程资源的过程。其中,“本机”是指本地物理机(假定本地物理机的ip为172.8.8.8),“远程”是指内网云环境(假定远程主机的ip为172.6.6.6,操作系统为ubtunu,用户名为ubuntu)。
一、nginx反向代理
在远程环境配置nginx相关服务的反向代理策略,便可以在本机访问那些只能在远程环境访问的资源了。具体配置方式如下:
如果不加特殊说明,下述操作均在远程环境中进行!
- 安装nginx
sudo apt install nginx
- 配置nginx
sudo vim /etc/nginx/nginx.conf
load_module /usr/lib/nginx/modules/ngx_stream_module.so;
events {
}
http {
server
{
listen 80;
server_name http.resource.com;
location / {
proxy_pass http://http.resource.com:80;
}
}
server
{
listen 443;
server_name https.resource.com;
ssl on;
ssl_certificate /etc/nginx/nginx.crt; # sudo openssl req -x509 -nodes -days 36500 -newkey rsa:2048 -keyout /etc/nginx/nginx.key -out /etc/nginx/nginx.crt
ssl_certificate_key /etc/nginx/nginx.key;
location / {
proxy_pass https://https.resource.com:443;
}
}
}
stream
{
server
{
listen 6666;
proxy_pass tcp.resource.com:6666;
}
}
- 启用nginx服务
sudo systemctl start nginx
sudo systemctl enable nginx
- 在本机配置hosts
sudo vim /etc/hosts
172.6.6.6 http.resource.com
172.6.6.6 https.resource.com
172.6.6.6 tcp.resource.com
- 在本机访问远程资源
curl http://http.resource.com
curl https://https.resource.com
telnet tcp.resource.com 6666
- 其它可选配置:访问控制
nginx支持通过allow和deny配置ip白名单和黑名单,达到访问控制的目的。
sudo vim /etc/nginx/nginx.conf
http {
allow 172.8.8.8.; # 本机ip
deny all;
#...
server {
allow 172.8.8.8.;
deny all;
# ...
}
allow与deny分别表示白名单和黑名单,上述配置表示除了172.8.8.8能访问这台服务器外,其它的ip都不允许访问。其中,server会覆盖http级别的allow和deny配置。
为了更进一步地控制,也可以使用系统的防火墙,如iptables、ufw等等。
- 其它可选配置:泛域名统一转发
正常情况下,一个server只能配置一个域名的转发。泛域名统一转发支持相同域名前缀或后缀(如company.com)的所有域名,只需要使用一个server,就可以完成统一的转发,以简化server的配置。
sudo vim /etc/nginx/nginx.conf
server
{
listen 80;
resolver 127.0.0.53; # 配置域名解析服务
server_name *.company.com; # 泛域名
location / {
proxy_pass http://$host; # 直接转发到server_name对应的域名
}
}
其等价于:
{
listen 80;
server_name a.company.com;
location / {
proxy_pass http://a.company.com;
}
}
{
listen 80;
server_name b.company.com;
location / {
proxy_pass http://b.company.com;
}
}
{
listen 80;
server_name c.company.com;
location / {
proxy_pass http://c.company.com;
}
}
可以看到,泛域名统一转发要简洁地多。假设nginx所在的主机已经有了a.company.com、b.company.com、c.company.com的dns记录(如果没有,在nginx所在的主机配置host即可),那么上述配置将直接支持所有相关域名的转发。随后,配置本机host:
172.6.6.6 a.company.com
172.6.6.6 b.company.com
172.6.6.6 c.company.com
本机访问即可自动转发到真正的*.company.com:
curl http://a.company.com
curl http://b.company.com
curl http://c.company.com
二、ssh转发
ssh转发分为本地转发、远程转发、动态代理、TCP转发、跳板连接等方式:
- 本地转发(
-L):在本地开一个端口,并通过这个端口访问远程服务,适用于将远程资源转发到本地的情况(这里的远程资源包括远程主机自己的服务资源,也包括远程主机能够访问到的其它主机的服务资源)。 - 远程转发(
-R):在远程开一个端口,并通过这个端口访问本地服务,适用于将本地资源转发到远程的情况(这里的本地资源包括本地主机自己的服务资源,也包括本地主机能够访问到的其它主机的服务资源,如:外网资源等)。 - 动态代理(
-D):在本地开一个端口,并通过这个端口建立访问远程服务的socks5代理,适用于动态将远程资源转发到本地的情况。 - TCP转发(
-W):直接转发TCP数据流,可以代理git请求(配合ssh的ProxyCommand配置一起使用)。 - 跳板连接(
-J):通过跳板机,直接访问远程SSH资源(通过ssh的ProxyJump配置简化使用过程)。
(一)本地转发
- 在本机启用本地转发
ssh -L 8080:http.resource.com:80 ubuntu@172.6.6.6 -N
-L表明启用ssh本地转发。这里将http.resource.com:80远程资源转发到了本机的8080端口。
- 在本机配置hosts
sudo vim /etc/hosts
127.0.0.1 http.resource.com
- 在本机访问远程资源
curl http://http.resource.com:8080
(二)远程转发
- 在本机启用远程转发
ssh -R 8080:www.baidu.com:443 ubuntu@172.6.6.6 -N
-R表明启用ssh远程转发。这里将www.baidu.com:443本机资源转发到了远程的8080端口。
- 在远程环境配置hosts
sudo vim /etc/hosts
127.0.0.1 www.baidu.com
- 在远程环境访问本地(外网)资源
curl https://www.baidu.com:8080
(三)动态代理
- 启用动态转发代理
ssh -D 127.0.0.1:8080 ubuntu@172.6.6.6 -N
- 在浏览器配置代理
在浏览器中安装代理切换插件,如:SwitchyOmega等。
- 在curl配置代理(可选)
# 代理时使用本地DNS
curl -x socks5://127.0.0.1:8080 http.resource.com
curl --socks5 127.0.0.1:8080 http.resource.com
# 代理时使用远程DNS
curl -x socks5h://127.0.0.1:8080 http.resource.com
curl --socks5-hostname 127.0.0.1:8080 http.resource.com
- 在kubeconfig中配置代理(可选)
vim ~/.kube/config
clusters:
- cluster:
proxy-url: socks5://127.0.0.1:8080
server: https://k8s.resource.com
- 在maven中配置代理(可选)
(1)socks代理临时生效
export MAVEN_OPTS="-DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 -DsocksNonProxyHosts=maven.aliyun.com"
mvn clean package -DskipTests
(2)socks代理全局生效
mkdir -p ~/.mvn
echo "-DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 -DsocksNonProxyHosts=maven.aliyun.com" >> ~/.mvn/jvm.config
(3)http代理
除了上述基于maven环境变量让JVM底层使用socks代理外,maven也支持通过settings.xml文件的proxies项来配置代理,但该配置只支持http协议,不支持ssh的socks协议。对于这种情况,可以通过privoxy等工具,将socks协议转换成http代理,然后配置settings.xml文件的proxies项,具体详见附录。
- 在本机git配置代理(可选)
cat >> ~/.ssh/config << EOF
Host git.resource.com
ProxyCommand ncat --proxy 127.0.0.1:8080 --proxy-type socks5 %h %p
EOF
ProxyCommand的值自定义了TCP代理转发的过程,nc、ncat、socat等命令都可以实现类似的功能,安装任意一个即可。同时,
ssh -W也支持TCP流量转发(推荐),详见下文。
(四)TCP转发
- 在本机git配置代理(基于ssh的
-W参数)
cat >> ~/.ssh/config << EOF
Host git.resource.com
ProxyCommand ssh -W %h:%p 172.6.6.6
EOF
(五)跳板连接
- 基于ssh的
-J参数指定跳板机
ssh -J ubtunu@172.6.6.6 ssh.resource.com
- 基于ssh的
ProxyJump配置指定跳板机
cat >> ~/.ssh/config << EOF
Host ssh.resource.com
ProxyJump 172.6.6.6
EOF
ssh ssh.resource.com
三、vscode远程开发
Visual-Studio-Code(vscode)可以通过Remote插件(主要是Remote-SSH插件)来进行远程开发。
- 安装
Remote插件
在本机vscode的扩展中搜索Remote,找到对应项安装即可。
- 在远程环境中安装vscode-server
正常情况下,首次使用Remote连接远程环境时,远程环境会自动下载服务端vscode。
- 在本机vscode中连接远程环境
在vscode中点击远程资源管理器,在SSH Target项点击+,输入ssh ubuntu@172.6.6.6 -A,回车,选择/home/xxx/.ssh/conf,回车。在SSH Target下的172.6.6.6项点击右边图标,进入远程环境
至此,后续所有开发操作均和本地vscode操作一致了,如果需要支持特定语言,则需要安装对应插件(如:java)。
四、jetbrains远程开发
Jetbrains旗下有两款远程开发方案:Gateway及Projetctor。Gateway远程开发详见Gateway官方教程,Projetctor已过期,并合并至Gateway。
附录
Maven的HTTP代理配置
(1)基于ssh配置socks代理
ssh -D 127.0.0.1:8080 ubtunu@172.6.6.6 -N &
(2)配置systemd服务(可选)
mkdir -p ~/.config/systemd/user/
cat << EOF > ~/.config/systemd/user/ssh-tunnel.service
[Unit]
Description=SSH Dynamic Tunnel
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/ssh -D 127.0.0.1:8080 ubtunu@172.6.6.6 -N -o ExitOnForwardFailure=yes -o ServerAliveInterval=30
Restart=on-failure
RestartSec=10
[Install]
WantedBy=default.target
EOF
systemctl --user enable --now ssh-tunnel.service
(3)基于privoxy将socks转换成http
# 安装privoxy
sudo pacman -S privoxy
# 配置转发(默认listen-address配置为:127.0.0.1:8118,如果没有配置,需加上)
echo "forward-socks5t / 127.0.0.1:8080 ." | sudo tee -a /etc/privoxy/config
# 启用privoxy服务
sudo systemctl enable --now privoxy
(4)Maven配置修改
<settings>
<proxies>
<proxy>
<id>ssh-privoxy-proxy</id>
<active>true</active>
<protocol>http</protocol>
<host>127.0.0.1</host>
<port>8118</port>
<nonProxyHosts>maven.aliyun.com</nonProxyHosts>
</proxy>
</proxies>
</settings>
VSCode远程环境离线安装
在老版本的vscode中,如果远程环境没有外网的网络策略,需用手工在本地下载服务端vscode之后传输到远程环境进行离线安装。最新版本的vscode版本已经支持了“本地下载服务端vscode,并传输到远程环境”这一过程,本小节后续内容请忽略。
在本机下载vscode-server:
export VSCODE_COMMIT_ID=$(code -v | sed -n '2p') # 如果vscode的commit_id获取失败,请打开vscode,点击帮助,再点击关于,手动获取commit_id
wget https://update.code.visualstudio.com/commit:$VSCODE_COMMIT_ID/server-linux-x64/stable -O vscode-server-linux-x64-$VSCODE_COMMIT_ID.tar.gz # 下载vscode-server
scp vscode-server-linux-x64-$VSCODE_COMMIT_ID.tar.gz ubuntu@172.6.6.6:/home/ubuntu # 上传vscode-server
在远程环境离线安装vscode-server:
export VSCODE_COMMIT_ID=$(ls ~/vscode-server-linux-x64-* | cut -d '-' -f 5 | cut -d '.' -f 1)
mkdir -p ~/.vscode-server/bin/
cd ~/.vscode-server/bin/
mv ~/vscode-server-linux-x64-*.tar.gz .
tar zxvf vscode-server-linux-x64-*.tar.gz
mv vscode-server-linux-x64 $VSCODE_COMMIT_ID
Projetctor远程环境离线安装
Projetctor已过期,并合并至Gateway,本小节后续内容请忽略。
- 在远程环境安装projetctor服务端
docker pull jetbrains/projector-idea-c
docker run --rm -p 8887:8887 -it jetbrains/projector-idea-c
有三种方式安装projetctor服务端:python方式(projector-installer)、idea插件方式projector-server-plugin、docker方式(projector-docker),这里以docker方式为例。
如果云环境无法访问docker仓库,可以使用ssh远程转发临时代理docker仓库
- 在本机连接projetctor服务
有两种方式可以连接projetctor服务:
- Web Client:直接在浏览器中输入
http://172.6.6.6:8887即可访问远程IDE。 - Native App:安装projectorr-client客户端,并通过客户端访问远程IDE。