``` https://github.com/juanfont/headscale/releases/download/v0.27.1/headscale_0.27.1_linux_amd64 https://raw.githubusercontent.com/juanfont/headscale/main/config-example.yaml mkdir /var/lib/headscale chown -R headscale:headscale /var/lib/headscale/ touch /var/lib/headscale/db.sqlite headscale_0.27.1_linux_amd64 /usr/local/bin/headscale chmod +x /usr/local/bin/headscale mkdir /etc/headscale/ cp config-example.yaml /etc/headscale/ ``` ``` 修改配置文件,将 server_url 改为公网 IP 或域名。如果是国内服务器,域名必须要备案。我的域名无法备案,所以我就直接用公网 IP 了。 如果暂时用不到 DNS 功能,可以先将 magic_dns 设为 false。 server_url 设置为 http://:8080,将 替换为公网 IP 或者域名。 建议打开随机端口,将 randomize_client_port 设为 true。 可自定义私有网段,也可同时开启 IPv4 和 IPv6: ip_prefixes: # - fd7a:115c:a1e0::/48 - 100.64.0.0/16 ``` #### vim /etc/systemd/system/headscale.service ``` [Unit] Description=headscale controller After=syslog.target After=network.target [Service] Type=simple User=headscale Group=headscale ExecStart=/usr/local/bin/headscale serve Restart=always RestartSec=5 # Optional security enhancements NoNewPrivileges=yes PrivateTmp=yes ProtectSystem=strict ProtectHome=yes ReadWritePaths=/var/lib/headscale /var/run/headscale AmbientCapabilities=CAP_NET_BIND_SERVICE RuntimeDirectory=headscale [Install] WantedBy=multi-user.target ``` #### 需要# 启用IP转发 ``` echo 'net.ipv4.ip_forward=1' | tee -a /etc/sysctl.conf sysctl -p ``` ##### 配置NAT规则(以eth0为外网接口) ``` apt install iptables-persistent iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE iptables -t filter -A FORWARD -i tailscale0 -o eth0 -j ACCEPT iptables -t filter -A FORWARD -i eth0 -o tailscale0 -m state --state RELATED,ESTABLISHED -j ACCEPT netfilter-persistent save ``` #### 启用出口节点模式 ``` tailscale up --advertise-exit-node ``` #### 启动 ``` systemctl daemon-reload systemctl enable --now headscale systemctl status headscale.service ``` #### 完整 egrep -v "#|^$" /etc/headscale/config.yaml ``` egrep -v "#|^$" /etc/headscale/config.yaml --- server_url: http://47.106.140.17:8080 listen_addr: 0.0.0.0:8080 metrics_listen_addr: 127.0.0.1:9090 grpc_listen_addr: 0.0.0.0:50443 grpc_allow_insecure: false noise: private_key_path: /var/lib/headscale/noise_private.key prefixes: v4: 100.64.0.0/10 v6: fd7a:115c:a1e0::/48 allocation: sequential derp: server: enabled: false region_id: 999 region_code: "headscale" region_name: "Headscale Embedded DERP" verify_clients: true stun_listen_addr: "0.0.0.0:3478" private_key_path: /var/lib/headscale/derp_server_private.key automatically_add_embedded_derp_region: true ipv4: 198.51.100.1 ip_allocation: "sequential" acl: - action: "accept" urls: - https://controlplane.tailscale.com/derpmap/default paths: [] auto_update_enabled: true update_frequency: 3h disable_check_updates: false ephemeral_node_inactivity_timeout: 30m database: type: sqlite debug: false gorm: prepare_stmt: true parameterized_queries: true skip_err_record_not_found: true slow_threshold: 1000 sqlite: path: /var/lib/headscale/db.sqlite write_ahead_log: true wal_autocheckpoint: 1000 acme_url: https://acme-v02.api.letsencrypt.org/directory acme_email: "" tls_letsencrypt_hostname: "" tls_letsencrypt_cache_dir: /var/lib/headscale/cache tls_letsencrypt_challenge_type: HTTP-01 tls_letsencrypt_listen: ":http" tls_cert_path: "" tls_key_path: "" log: level: info format: text policy: mode: file path: "" dns: magic_dns: false base_domain: rapha.top override_local_dns: true nameservers: global: - 114.114.114.114 - 233.5.5.5 - 1.1.1.1 - 8.8.8.8 split: {} search_domains: [] extra_records: [] unix_socket: /var/run/headscale/headscale.sock unix_socket_permission: "0770" logtail: enabled: false randomize_client_port: false ``` ### 创建用户 ``` headscale user create cba ``` ### 查看用户 ``` # headscale user list ID | Name | Username | Email | Created 1 | | cba | | 2025-12-11 14:11:53 2 | | abc | | 2025-12-13 12:23:02 ``` ### linux cli 配置 ``` wget https://pkgs.tailscale.com/stable/tailscale_1.22.2_amd64.tgz tar zxvf tailscale_1.22.2_amd64.tgz cp tailscale_1.22.2_amd64/tailscaled /usr/sbin/tailscaled cp tailscale_1.22.2_amd64/tailscale /usr/bin/tailscale cp tailscale_1.22.2_amd64/systemd/tailscaled.service /lib/systemd/system/tailscaled.service cp tailscale_1.22.2_amd64/systemd/tailscaled.defaults /etc/default/tailscaled ``` ``` systemctl enable --now tailscaled systemctl status tailscaled ``` #### Tailscale 接入 Headscale: ``` ## 如果你是在自己的服务器上部署的,请将 换成你的 Headscale 公网 IP 或域名 tailscale up --login-server=http://47.106.140.17:8080 --accept-routes=true --accept-dns=false ``` ### 将其中的命令复制粘贴到服务段 headscale 所在机器的终端中,并将 USERNAME 替换为前面所创建的 user。 headscale nodes register --key ZR12m7dvnPUgbbfkx_FdMUvW --user cba ``` ``` #### 注册成功,查看注册的节点: ``` # headscale nodes list ID | Hostname | Name | MachineKey | NodeKey | User | IP addresses | Ephemeral | Last seen | Expiration | Connected | Expired 1 | localhost | localhost | [ZqdSj] | [qxtoU] | cba | 100.64.0.1, fd7a:115c:a1e0::1 | false | 2025-12-13 15:03:06 | 0001-01-01 00:00:00 | offline | no 2 | smb-kk | smb-kk | [6+OpS] | [ZOUQN] | abc | 100.64.0.2, fd7a:115c:a1e0::2 | false | 2025-12-13 14:42:15 | 0001-01-01 00:00:00 | online | no ``` #### 回到 Tailscale 客户端所在的 Linux 主机,可以看到 Tailscale 会自动创建相关的路由表和 iptables 规则。路由表可通过以下命令查看 ``` # ip route show table 52 100.64.0.1 dev tailscale0 100.100.100.100 dev tailscale0 ``` #### 查看 iptables 规则: ``` # iptables -S -P INPUT ACCEPT -P FORWARD DROP -P OUTPUT ACCEPT -N DOCKER -N DOCKER-BRIDGE -N DOCKER-CT -N DOCKER-FORWARD -N DOCKER-ISOLATION-STAGE-1 -N DOCKER-ISOLATION-STAGE-2 -N DOCKER-USER -N ts-forward -N ts-input -A INPUT -j ts-input -A FORWARD -j ts-forward -A FORWARD -j DOCKER-USER -A FORWARD -j DOCKER-FORWARD -A DOCKER ! -i docker0 -o docker0 -j DROP -A DOCKER-BRIDGE -o docker0 -j DOCKER -A DOCKER-CT -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-FORWARD -j DOCKER-CT -A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1 -A DOCKER-FORWARD -j DOCKER-BRIDGE -A DOCKER-FORWARD -i docker0 -j ACCEPT -A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2 -A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP -A DOCKER-USER -j RETURN -A ts-forward -i tailscale0 -j MARK --set-xmark 0x40000/0xff0000 -A ts-forward -m mark --mark 0x40000/0xff0000 -j ACCEPT -A ts-forward -s 100.64.0.0/10 -o tailscale0 -j DROP -A ts-forward -o tailscale0 -j ACCEPT -A ts-input -s 100.64.0.2/32 -i lo -j ACCEPT -A ts-input -s 100.115.92.0/23 ! -i tailscale0 -j RETURN -A ts-input -s 100.64.0.0/10 ! -i tailscale0 -j DROP -A ts-input -i tailscale0 -j ACCEPT -A ts-input -p udp -m udp --dport 41641 -j ACCEPT ```