Categories
VPS 科普

如何使用共享IP虚拟主机而不失霸气

本文会探讨一下不使用端口映射的情况下如歌使用共享 IP 主机。

关于独享与共享:有些特定场景是必须独享 IP 的,比如基于 SIP 协议的 VoIP 语音系统或 H.323/T.120 的网络视频会议设备都不能在共享公网 IP 的场景下运作。但其实很多时候你并不需要独享 IP 的主机。

由于不可描述的原因并根据站长非正式统计,中国是现时云主机个人均拥有量最高的地区,没有之一。伴随这庞大需求而来的是各路厂商对成本的最大优化而衍生的各类阉割版主机,务求以低价与薄利多销的策略来吸引消费者。而对个人使用的低阶主机产品而言,已经属于稀缺资源的公网 IPv4 就占了成本的一大部分(本文的 IP 都是泛指 v4,后略)。于是市面上出现了各种各样的共享公网 IP 或 NAT 主机租赁服务。

没有不能够玩的鸡,只有不会玩鸡的人(误)

Jitdor Tech Tips

一般的 NAT 主机服务都会提供特定数量的端口供映射/转发 (port forwarding) 设置。使用该些主机技术含量不高,这里就不赘述了。本文主要目的是教大家如何使用不带端口映射的共享 IP 主机,例如:

  • 在公司、学校或你没有管理员权限的网络内挂的主机;
  • 你的网络商使用了极其恶心的电信级 NAT (Carrier-grade NAT) 而你需要从外网连接家里的主机或 NAS;
  • 你为了节省开支而开了没挂公网 IP 的云主机(在 Azure 或 GCP 里这个操作可以为你省下每月每主机约 $3 美元的费用);
  • 你开的是只有 IPv6 公网的主机(如 Vultr 的乞丐机),不自带 IPv4 公网地址但可以外访 IPv4 网络;
  • 服务商出于防止端口扫描/嗅探的手段,把虚拟机状态策略设定为允许内网连接外网,但拒绝外网主动连入内网

如果你的共享主机是以上任何一种情况,你需要设置内网穿透才能从外网访问你的主机。所需要的材料有:

  1. 堡垒机 (jump server) 一台(带公网 IP 并可以从外网连入的主机,或是你家电脑)
  2. 需要 “被穿透” 的 NAT 主机一台
  3. 时间和耐心成本

当然你可以用花生壳或类似产品,但免费版的局限繁多(限速限端口限连接数限域名等等),并不能满足本站读者的折腾需求。而且必须自己动手,才能丰衣足食。

方法 1:frp

frpGithub 主页提供了颇为详细的文档和使用示例。frp 分为服务端 (frps) 和客户端 (frpc) 两部分。假设我们需要从外网以 TCP 协议访问不带端口映射的 NAT 主机 443 端口,可以使用以下配置

堡垒机 frps.ini (服务端)设置:

[common]
bind_port = 7000

NAT 主机 frpc.ini (客户端)设置:

[common]
server_addr = x.x.x.x <堡垒机的IP>
server_port = 7000
[服务的名字随便填,如 ws_tls]
type = tcp
local_ip = 127.0.0.1
local_port = 443
remote_port = 6000

在堡垒机和 NAT 主机都分别启动了 frpsfrpc 后,所有对堡垒机 x.x.x.x:6000 端口的请求将会被转发到 NAT 主机的 :443 端口。由于是从 NAT 主机主动对堡垒机发出的请求,我们不需要知道 NAT 主机的外网 IP 地址。无论 NAT 主机的 IP 如何改变,只要堡垒机的 IP 不变,这个配置会一直有效。

frp 另外也提供点对点内网穿透模式,来适配传输大量数据时流量不必经过堡垒机的场景。此时堡垒机的 frps 配置需要添加额外的 UDP 端口,如:

[common]
bind_port = 7000
bind_udp_port = 7001

NAT 主机的 frpc 配置如下,注意这里不需要指定远程端口:

[common]
server_addr = x.x.x.x <堡垒机的IP>
server_port = 7000

[ws_tls]
type = xtcp
# 只有 sk 一致的用户才能访问到此服务
sk = abcdefg
local_ip = 127.0.0.1
local_port = 443

最后在你要和 NAT 主机建立点对点传输的电脑启动另一个 frpc,配置如下:

[common]
server_addr = x.x.x.x <堡垒机的IP>
server_port = 7000
[ws_tls_visitor]
type = xtcp
role = visitor
# 要访问的 xtcp 代理的名字
server_name = ws_tls
sk = abcdefg
# 绑定本地端口用于访问 ws_tls 服务
bind_addr = 127.0.0.1
bind_port = 6000

设置完成并运行 frpc 后,你电脑端发出的 localhost:6000 请求将会以点对点的方式通往 NAT 主机的 :443 端口。

frp 还支持很多比如 DNS 转发、代理限速和负载均衡等等的骚操作。详细配置可以参考 Github 的项目页。

方法 2:v2ray

v2ray 本身也提供类似的内网穿透功能,让 NAT 主机里运行的 v2ray 端主动向堡垒机发出连接请求,而客户端发往堡垒机的请求会被直接转发到 NAT 主机,使用上提供与直连一样的体验。选择 v2ray 显而易见的优势是兼容现有的客户端,不需要安装新的软体便能直接使用。而服务端方面只需稍微更改配置就能实现该转发功能。

以下是我在使用的配置。堡垒机安装 Caddy 统一监听 443 端口,来自 NAT 主机的请求被反向代理到 16384 端口,来自客户端的请求则反向代理到 12345 端口。

堡垒机的 Caddyfile 配置:

your_domain.com {
  tls [email protected]
  root /var/www/path
  proxy /from_client localhost:12345 {
    websocket
    header_upstream -Origin
  }
  proxy /from_nat localhost:16384 {
    websocket
    header_upstream -Origin
  }
}

堡垒机的 v2ray 配置:

{
  "reverse": {
    "portals": [
      {
        "tag": "portal",
        "domain": "your_domain.com"
      }
    ]
  },
  "inbounds": [
    {
      "tag": "portalin",
      "port": 12345,
	  "listen": "127.0.0.1",
      "protocol": "vmess",
      "settings": {
        "clients": [
          {
            "id": "客户端的UUID",
            "alterId": 64
          }
        ]
      },
	  "streamSettings": {
	    "network": "ws",
		"wsSettings": {
		  "path": "/from_client"
		}
	  }
    },
    {
      "tag": "interconn",
      "port": 16384,
	  "listen": "127.0.0.1",
      "protocol": "vmess",
      "settings": {
        "clients": [
          {
            "id": "NAT主机的UUID",
            "alterId": 64
          }
        ]
      },
	  "streamSettings": {
	    "network": "ws",
		"wsSettings": {
		  "path": "/from_nat"
		}
	  }
    }
  ],
  "routing": {
    "rules": [
      {
        "type": "field",
        "inboundTag": [
          "portalin"
        ],
        "outboundTag": "portal"
      },
      {
        "type": "field",
        "inboundTag": [
          "interconn"
        ],
        "outboundTag": "portal"
      }
    ]
  }
}

这是 NAT 主机的配置:

{
  "reverse": {
    "bridges": [
      {
        "tag": "bridge",
        "domain": "your_domain.com"
      }
    ]
  },
  "outbounds": [
    {
      "tag": "bridgeout",
      "protocol": "freedom"
    },
    {
      "protocol": "vmess",
      "settings": {
        "vnext": [
          {
            "address": "your_domain.com",
            "port": 443,
            "users": [
              {
                "id": "NAT主机的UUID",
                "alterId": 64
              }
            ]
          }
        ]
      },
	  "streamSettings": {
	  	"network": "ws",
		"security": "tls",
		"wsSettings": {
		  "path": "/from_nat"
		}
	  },
      "tag": "interconn"
    }
  ],
  "routing": {
    "rules": [
      {
        "type": "field",
        "inboundTag": [
          "bridge"
        ],
        "domain": [
          "full:your_domain.com"
        ],
        "outboundTag": "interconn"
      },
      {
        "type": "field",
        "inboundTag": [
          "bridge"
        ],
        "outboundTag": "bridgeout"
      }
    ]
  }
}

最后是要连接到 NAT 主机的客户端的基本配置:

{
  "inbounds": [
    {
      "port": 1080,
      "listen": "127.0.0.1",
      "protocol": "socks",
      "sniffing": {
        "enabled": true,
        "destOverride": [
          "http",
          "tls"
        ]
      },
  ],
  "outbounds": [
    {
      "protocol": "vmess",
      "settings": {
        "vnext": [
          {
            "address": "your_domain.com",
            "port": 443,
            "users": [
              {
                "id": "客户端的UUID",
                "alterId": 64,
                "email": "[email protected]",
                "security": "auto"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "ws",
        "security": "tls",
        "wsSettings": {
          "path": "/from_client",
          "headers": {
            "Host": "your_domain.com"
          }
        }
      }
    }
  ]
}

以上的配置可以用以下的图来表达:

A = NAT 主机
B = 堡垒机
C = 客户端

起初看来会有点复杂,多看几遍不明白也没关系,把配置照搬就可以见证奇迹的时刻了。使用起来你将不会感觉到堡垒机的存在。

Leave a Reply