frist
This commit is contained in:
71
internal/security/validate_url.go
Normal file
71
internal/security/validate_url.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package security
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/url"
|
||||
|
||||
"proxyrotator/internal/model"
|
||||
)
|
||||
|
||||
// ValidateTestURL 校验测试目标 URL,防止 SSRF
|
||||
func ValidateTestURL(rawURL string) error {
|
||||
u, err := url.Parse(rawURL)
|
||||
if err != nil {
|
||||
return model.ErrInvalidURL
|
||||
}
|
||||
|
||||
// 只允许 http/https
|
||||
if u.Scheme != "http" && u.Scheme != "https" {
|
||||
return model.ErrUnsafeScheme
|
||||
}
|
||||
|
||||
// 解析主机名
|
||||
host := u.Hostname()
|
||||
if host == "" {
|
||||
return model.ErrInvalidURL
|
||||
}
|
||||
|
||||
// 解析 IP 地址
|
||||
ips, err := net.LookupIP(host)
|
||||
if err != nil {
|
||||
return model.ErrInvalidURL
|
||||
}
|
||||
|
||||
// 检查是否为私网 IP
|
||||
for _, ip := range ips {
|
||||
if IsPrivateIP(ip) {
|
||||
return model.ErrPrivateIP
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsPrivateIP 判断是否为私网 IP
|
||||
func IsPrivateIP(ip net.IP) bool {
|
||||
if ip == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// 回环地址
|
||||
if ip.IsLoopback() {
|
||||
return true
|
||||
}
|
||||
|
||||
// 链路本地地址
|
||||
if ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() {
|
||||
return true
|
||||
}
|
||||
|
||||
// 私有地址
|
||||
if ip.IsPrivate() {
|
||||
return true
|
||||
}
|
||||
|
||||
// 未指定地址
|
||||
if ip.IsUnspecified() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user