flipped-aurora/gin-vue-admin · warning
目标解析为内网/环回/链路本地地址, 已被 SSRF 防护拒绝(可在任务上开启"允许内网"豁免)
Error message
目标解析为内网/环回/链路本地地址, 已被 SSRF 防护拒绝(可在任务上开启"允许内网"豁免)
What it means
errPrivateAddr is the sentinel returned by the HTTP task executor's SSRF protection when the target URL resolves to a loopback, private (RFC1918), link-local, multicast link-local, or unspecified IP. It prevents server-side request forgery against internal networks; tasks can opt out via an "allow intranet" flag.
Source
Thrown at server/service/system/sys_timed_task_http.go:14
// server/service/system/sys_timed_task_http.go
package system
import (
"errors"
"fmt"
"net"
"net/http"
"syscall"
"time"
)
// errPrivateAddr SSRF 防护拒绝(错误信息含"SSRF"关键字, 供日志/测试识别)
var errPrivateAddr = errors.New("目标解析为内网/环回/链路本地地址, 已被 SSRF 防护拒绝(可在任务上开启\"允许内网\"豁免)")
// isDisallowedIP 内网/环回/链路本地/未指定地址判定
func isDisallowedIP(ip net.IP) bool {
return ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() || ip.IsUnspecified()
}
// ssrfControl 在拨号阶段(DNS 解析后、连接建立前)校验目标 IP:
// 每次连接都过检, 天然覆盖重定向与 DNS rebinding(TOCTOU 安全)。
func ssrfControl(allowPrivate bool) func(network, address string, c syscall.RawConn) error {
return func(_ string, address string, _ syscall.RawConn) error {
if allowPrivate {
return nil
}
host, _, err := net.SplitHostPort(address)
if err != nil {
return fmt.Errorf("解析拨号地址失败: %w", err)
}
ip := net.ParseIP(host)View on GitHub (pinned to 3136500ef3)
Solutions
- If the target is intentionally internal, enable the task's "允许内网" (allow intranet) exemption flag.
- Use a publicly reachable https:// endpoint for the task target.
- Check DNS resolution of the hostname; if it resolves to a private IP unexpectedly, fix DNS or use the public address.
- Avoid loopback/unspecified addresses like localhost or 0.0.0.0 unless exempted.
Example fix
// before HttpUrl: "http://127.0.0.1:8080/health" // rejected by SSRF guard // after task.AllowIntranet = true HttpUrl: "http://127.0.0.1:8080/health" // allowed with explicit exemption // or HttpUrl: "https://api.example.com/health"
Defensive patterns
Strategy: try-catch
Validate before calling
ips, err := net.LookupIP(u.Hostname())
if err == nil {
for _, ip := range ips {
if ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() || ip.IsUnspecified() {
if !task.AllowIntranet {
return errors.New("target resolves to a private address; enable allow-intranet or use a public endpoint")
}
}
}
} Try / catch
if err := runner.RunTask(ctx, task); err != nil {
if strings.Contains(err.Error(), "SSRF") {
log.Warnf("task %s blocked by SSRF guard; target is internal", task.Name)
return
}
log.Errorf("task %s failed: %v", task.Name, err)
} Prevention
- Use public endpoints for scheduled HTTP tasks
- Enable the allow-intranet exemption only for intentionally internal targets
- Check what hostnames resolve to before configuring tasks
- Avoid localhost/0.0.0.0 targets in shared environments
When it happens
Trigger: Running/creating an HTTP-executor timed task whose URL host is 127.0.0.1, ::1, 10.x, 172.16-31.x, 192.168.x, 169.254.x, 0.0.0.0, or a DNS name resolving to any of these, without the allow-intranet exemption enabled on the task.
Common situations: Pointing tasks at internal microservices (http://localhost:8080/...) in dev configs; docker-compose service names resolving to private IPs; staging tasks moved from public to private endpoints; corporate DNS resolving to internal ranges.
Related errors
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/2d3dc345a6a0ee03.
Report an issue: GitHub.