Tiven Wang
Wang Tiven June 18, 2018
425 favorite favorites
bookmark bookmark
share share

家庭网络怎么做云服务,实际上就是如何将内网服务暴露到公网环境,这里的内网环境的路由一般是指家庭的拨号上网方式,其公网 IP 会不断变换,所以主要解决的就是动态 DNS 或者叫内网穿透。

DDNS

动态 DNS 的原理就是客户主机不断发送自己的 IP 信息给具有 DNS 功能的服务器,

需要路由器设置端口转发?

上报自己的信息代码示例

原理就是循环间隔向服务器发送请求上报自己的 IP 信息

https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions

forever js is a simple CLI tool for ensuring that a given script runs continuously.

https://www.digitalocean.com/community/tutorials/how-to-create-temporary-and-permanent-redirects-with-apache-and-nginx

pubic server

const http = require('http');
const fs = require('fs');

const hostname = '0.0.0.0';
const port = 3000;

const server = http.createServer((req, res) => {
  let ip = req.headers["x-forwarded-for"] || req.socket.remoteAddress;

  fs.writeFile('ips.txt', ip, function (err) {
    if (err) throw err;
    console.log('Saved!');
  });

  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

http client in home network

const http = require('http');

setInterval(() => {
  http.get('http://<pubic_id>:3000', (resp) => {
    let data = '';

    // A chunk of data has been recieved.
    resp.on('data', (chunk) => {
      data += chunk;
    });

    // The whole response has been received. Print out the result.
    resp.on('end', () => {
      console.log(new Date());
    });
  }).on("error", (err) => {
    console.log("Error: " + err.message);
  });
}, 10*60*1000);

https://cloudplatform.googleblog.com/2018/06/Now-you-can-deploy-your-Node-js-app-to-App-Engine-standard-environment.html?m=1

https://cloud.google.com/appengine/docs/standard/nodejs/quickstart

DDNS 产品

Docker DDNS

后来仔细找了一下就发现了 docker-ddns: Dynamic DNS with Docker, Go and Bind9 这个实现此功能,就不需要自己再繁琐地写代码了(除非我想练习)。

Run Docker-DNS container

下面在你的 VPS 服务器上运行下面的 Docker 容器

docker run -it -d \
    -p 8080:8080 \
    -p 53:53 \
    -p 53:53/udp \
    -e SHARED_SECRET=your-secret \
    -e ZONE=tiven.wang \
    -e RECORD_TTL=3600 \
    --name=ddns \
    davd/docker-ddns:latest

这样有可能因为 53 端口已经被占用而启动失败(通过命令 sudo lsof -Pnl +M -i4 | grep 53 可以查看端口号被谁占用着),使用命令 sudo systemctl status systemd-resolved.service 查看服务 systemd-resolved 的运行状态,如果在运行可以通过以下方式关闭它 编辑文件 /etc/systemd/resolved.conf 添加配置 DNSStubListener=no 然后重启服务 sudo systemctl restart systemd-resolved.service

配置域名解析

为你的 VPS 分配一个域名,如 ddns.tiven.wang(这是一条 A 记录域名指向你的 VPS 固定 IP)。然后把你要动态解析的域名设置为 NS 记录并指向前面设置的 VPS 域名(如我的是 ddns.tiven.wang)。

测试动态解析

使用 GET 请求地址 http://ddns.tiven.wang:8080/update?secret=your-secret&domain=home&addr=30.190.219.20 便可设置你的域名(如我的 home.tiven.wang)指向某个 IP。

NOIP

or https://www.noip.com/

or https://hub.docker.com/r/dragoncube/google-domains-ddns/

https://domains.google/#/

or https://www.duckdns.org/

or https://github.com/oznu/docker-cloudflare-ddns

cloudflare dns servers: gabe.ns.cloudflare.com tricia.ns.cloudflare.com

DDNS 并不合适,有的需要费用,noip 的 DNS 可能被墙内污染了。

ngrok

https://ngrok.com/

VPS+VPN+IPFORWARD👌

如果你已经有现有的域名和 VPS 可以选择如下方式。

https://www.digitalocean.com/community/tutorials/how-to-forward-ports-through-a-linux-gateway-with-iptables

我想还可以用 WireGuard 加密协议(走的是 UDP 协议效率很高)和 TunSafe 客户端(因为 Windows 系统使用 TunSafe 客户端比较方便,Ubuntu 等 Linux 系统可以用 WireGuard 程序)实现双向内网穿透的相互访问。WireGuard 加密协议是在两台电脑之间建立一个虚拟局域网,那么不管这两台电脑分别在哪里都可以使用局域网地址相互访问。例如:VPS 服务器(公网地址是 35.198.168.21)的 WireGuard 协议局域网地址是 10.0.0.1,家里的 Desktop 系统(不管公网地址是多少,因为它是会变的)的 WireGuard 协议地址是 10.0.0.2。那么用户用 (VPS 公网地址 35.198.168.21) + (端口号 80) 访问 VPS 服务器,VPS 服务器做 Iptables 转发给家庭主机的内网地址(10.0.0.2+8080)就可以实现访问了。不过麻烦的是,iptables 转发规则需要手动维护。

有没有脚本给做自动维护,再加个 Web 界面就可以了?

如何设置 Iptables 转发

设置 VPS 服务器的防火墙转发规则

sudo iptables -A FORWARD -i ens4 -o wg0 -p tcp --syn --dport 8080 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -i ens4 -o wg0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A FORWARD -i wg0 -o ens4 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -t nat -A PREROUTING -i ens4 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.2:8080
sudo iptables -t nat -A POSTROUTING -o wg0 -p tcp --dport 8080 -d 10.0.0.2 -j SNAT --to-source 10.0.0.1

要删除规则的话, 把添加规则时的参数 -A 改成 -D 就可以删除了

sudo iptables -D FORWARD -i ens4 -o wg0 -p tcp --syn --dport 8080 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -D FORWARD -i ens4 -o wg0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -D FORWARD -i wg0 -o ens4 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -t nat -D PREROUTING -i ens4 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.2:8080
sudo iptables -t nat -D POSTROUTING -o wg0 -p tcp --dport 8080 -d 10.0.0.2 -j SNAT --to-source 10.0.0.1

查看规则列表

sudo iptables -t nat -L -v -n

注意事项

需要注意的是你的家庭主机系统的防火墙可能需要对局域网进行相应端口开放,例如打开 Windows 10 firewall port 命令:

netsh advfirewall firewall add rule name="Open Port 8080 for HASS" dir=in action=allow protocol=TCP localport=8080

如果 Windows 还要转发给另外的主机系统,可以用 Windows 的端口转发规则

netsh interface portproxy add v4tov4 listenport=8080 listenaddress=10.0.0.2 connectport=8080 connectaddress=192.168.3.249

要删除的话用命令 netsh advfirewall firewall delete rule name="Open port 8080 for HASS"

Linux 系统的防火墙程序 ufw.

nginx

反向代理

docker run --name my-nginx -v %cd%/nginx.conf:/etc/nginx/nginx.conf:ro -d nginx

References

Similar Posts

Comments

Back to Top