自从用上了ddns以后,就想自己弄一个接口来获取vps的IP。
前几天在腾讯的Edgeone边缘函数和Cloudflare边缘函数上试过了,效果非常棒!
但是吧,他们都有限制,所以自己弄一个比较好。
听说go语言负载极强,所以决定使用go,最主要的还是之前没接触过go语言,但这一次接触觉得挺好玩。
需要预先部署go环境:
下面开始:
宝塔后台随便建一个静态网站:
进入到文件路径下:
新建一个 main.go 文件,填入代码:
也可以命令行操作:
cd /www/wwwroot/域名
sudo nano main.go
粘贴代码保存即可。
代码如下:
package main
import (
"fmt"
"net"
"net/http"
"strings"
)
func extractIP(addr string) string {
// 处理IPv6带端口的情况(格式为[IPv6]:port)
if strings.HasPrefix(addr, "[") {
// 去除方括号
end := strings.Index(addr, "]")
if end > 0 {
return addr[1:end]
}
}
// 处理IPv4带端口的情况
if idx := strings.LastIndex(addr, ":"); idx != -1 {
// 检查是否是IPv6地址(包含多个冒号)
if strings.Count(addr, ":") > 1 {
return addr // 已经是完整IPv6地址
}
return addr[:idx] // IPv4地址去除端口
}
return addr
}
func getIPHandler(w http.ResponseWriter, r *http.Request) {
var ip string
// 优先级顺序获取IP
if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
ips := strings.Split(xff, ",")
ip = strings.TrimSpace(ips[0])
} else if xrip := r.Header.Get("X-Real-IP"); xrip != "" {
ip = xrip
} else if cfip := r.Header.Get("CF-Connecting-IP"); cfip != "" {
ip = cfip
} else {
ip = r.RemoteAddr
}
// 特殊处理IPv6地址
ip = extractIP(ip)
fmt.Fprintf(w, "%s", ip)
}
func main() {
http.HandleFunc("/", getIPHandler)
fmt.Println("服务器启动成功,正在监听端口 8080...")
listener, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Printf("服务器启动失败: %v\n", err)
return
}
if err := http.Serve(listener, nil); err != nil {
fmt.Printf("服务器运行错误: %v\n", err)
}
}
代码填写完后,需要开始编译:
在ssh命令行下:
go build -o app main.go
chmod +x app
就两行代码编译后出现一个七八兆大小的app文件。
随后 ./app
执行即可。
长时间启动也可以像我一样使用宝塔,用“进程守护管理器”启动。
编译后使用Supervisor进程守护的配置:
访问你的:http://IP地址:8080
即可
需要开放端口,也可以使用nginx反向代理:
在nginx配置文件中填入即可:
location / {
proxy_pass http://localhost:8080;
proxy_set_header CF-Connecting-IP $http_cf_connecting_ip;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
}
端口可以自己定义,8080被其他程序占用就自己改端口,改完记得重新编译。
和Java一样,不愧是编译语言,动个符号都得重新编译。改bug还得是解释性语言好用。
注:目前代码还是有问题的,在使用cdn的情况下,在机器上curl ip
查询域名 返回的只有默认IP(可能是v4也可能是v6),不能添加-4
或-6
来指定获取IPv4或者IPv6的IP。
正文结束