Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
82163b4b
authored
Sep 17, 2025
by
creamlike1024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 添加域名启用ip过滤开关
parent
f9a6e7f0
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
31 additions
and
7 deletions
+31
-7
common/ssrf_protection.go
+8
-1
service/download.go
+2
-2
service/user_notify.go
+1
-1
service/webhook.go
+1
-1
setting/system_setting/fetch_setting.go
+2
-0
web/src/components/settings/SystemSetting.jsx
+17
-2
No files found.
common/ssrf_protection.go
View file @
82163b4b
...
@@ -16,6 +16,7 @@ type SSRFProtection struct {
...
@@ -16,6 +16,7 @@ type SSRFProtection struct {
IpFilterMode
bool
// true: 白名单, false: 黑名单
IpFilterMode
bool
// true: 白名单, false: 黑名单
IpList
[]
string
// CIDR or single IP
IpList
[]
string
// CIDR or single IP
AllowedPorts
[]
int
// 允许的端口范围
AllowedPorts
[]
int
// 允许的端口范围
ApplyIPFilterForDomain
bool
// 对域名启用IP过滤
}
}
// DefaultSSRFProtection 默认SSRF防护配置
// DefaultSSRFProtection 默认SSRF防护配置
...
@@ -276,6 +277,11 @@ func (p *SSRFProtection) ValidateURL(urlStr string) error {
...
@@ -276,6 +277,11 @@ func (p *SSRFProtection) ValidateURL(urlStr string) error {
return
fmt
.
Errorf
(
"domain in blacklist: %s"
,
host
)
return
fmt
.
Errorf
(
"domain in blacklist: %s"
,
host
)
}
}
// 若未启用对域名应用IP过滤,则到此通过
if
!
p
.
ApplyIPFilterForDomain
{
return
nil
}
// 解析域名对应IP并检查
// 解析域名对应IP并检查
ips
,
err
:=
net
.
LookupIP
(
host
)
ips
,
err
:=
net
.
LookupIP
(
host
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -296,7 +302,7 @@ func (p *SSRFProtection) ValidateURL(urlStr string) error {
...
@@ -296,7 +302,7 @@ func (p *SSRFProtection) ValidateURL(urlStr string) error {
}
}
// ValidateURLWithFetchSetting 使用FetchSetting配置验证URL
// ValidateURLWithFetchSetting 使用FetchSetting配置验证URL
func
ValidateURLWithFetchSetting
(
urlStr
string
,
enableSSRFProtection
,
allowPrivateIp
bool
,
domainFilterMode
bool
,
ipFilterMode
bool
,
domainList
,
ipList
,
allowedPorts
[]
string
)
error
{
func
ValidateURLWithFetchSetting
(
urlStr
string
,
enableSSRFProtection
,
allowPrivateIp
bool
,
domainFilterMode
bool
,
ipFilterMode
bool
,
domainList
,
ipList
,
allowedPorts
[]
string
,
applyIPFilterForDomain
bool
)
error
{
// 如果SSRF防护被禁用,直接返回成功
// 如果SSRF防护被禁用,直接返回成功
if
!
enableSSRFProtection
{
if
!
enableSSRFProtection
{
return
nil
return
nil
...
@@ -315,6 +321,7 @@ func ValidateURLWithFetchSetting(urlStr string, enableSSRFProtection, allowPriva
...
@@ -315,6 +321,7 @@ func ValidateURLWithFetchSetting(urlStr string, enableSSRFProtection, allowPriva
IpFilterMode
:
ipFilterMode
,
IpFilterMode
:
ipFilterMode
,
IpList
:
ipList
,
IpList
:
ipList
,
AllowedPorts
:
allowedPortInts
,
AllowedPorts
:
allowedPortInts
,
ApplyIPFilterForDomain
:
applyIPFilterForDomain
,
}
}
return
protection
.
ValidateURL
(
urlStr
)
return
protection
.
ValidateURL
(
urlStr
)
}
}
service/download.go
View file @
82163b4b
...
@@ -30,7 +30,7 @@ func DoWorkerRequest(req *WorkerRequest) (*http.Response, error) {
...
@@ -30,7 +30,7 @@ func DoWorkerRequest(req *WorkerRequest) (*http.Response, error) {
// SSRF防护:验证请求URL
// SSRF防护:验证请求URL
fetchSetting
:=
system_setting
.
GetFetchSetting
()
fetchSetting
:=
system_setting
.
GetFetchSetting
()
if
err
:=
common
.
ValidateURLWithFetchSetting
(
req
.
URL
,
fetchSetting
.
EnableSSRFProtection
,
fetchSetting
.
AllowPrivateIp
,
fetchSetting
.
DomainFilterMode
,
fetchSetting
.
IpFilterMode
,
fetchSetting
.
DomainList
,
fetchSetting
.
IpList
,
fetchSetting
.
AllowedPorts
);
err
!=
nil
{
if
err
:=
common
.
ValidateURLWithFetchSetting
(
req
.
URL
,
fetchSetting
.
EnableSSRFProtection
,
fetchSetting
.
AllowPrivateIp
,
fetchSetting
.
DomainFilterMode
,
fetchSetting
.
IpFilterMode
,
fetchSetting
.
DomainList
,
fetchSetting
.
IpList
,
fetchSetting
.
AllowedPorts
,
fetchSetting
.
ApplyIPFilterForDomain
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"request reject: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"request reject: %v"
,
err
)
}
}
...
@@ -59,7 +59,7 @@ func DoDownloadRequest(originUrl string, reason ...string) (resp *http.Response,
...
@@ -59,7 +59,7 @@ func DoDownloadRequest(originUrl string, reason ...string) (resp *http.Response,
}
else
{
}
else
{
// SSRF防护:验证请求URL(非Worker模式)
// SSRF防护:验证请求URL(非Worker模式)
fetchSetting
:=
system_setting
.
GetFetchSetting
()
fetchSetting
:=
system_setting
.
GetFetchSetting
()
if
err
:=
common
.
ValidateURLWithFetchSetting
(
originUrl
,
fetchSetting
.
EnableSSRFProtection
,
fetchSetting
.
AllowPrivateIp
,
fetchSetting
.
DomainFilterMode
,
fetchSetting
.
IpFilterMode
,
fetchSetting
.
DomainList
,
fetchSetting
.
IpList
,
fetchSetting
.
AllowedPorts
);
err
!=
nil
{
if
err
:=
common
.
ValidateURLWithFetchSetting
(
originUrl
,
fetchSetting
.
EnableSSRFProtection
,
fetchSetting
.
AllowPrivateIp
,
fetchSetting
.
DomainFilterMode
,
fetchSetting
.
IpFilterMode
,
fetchSetting
.
DomainList
,
fetchSetting
.
IpList
,
fetchSetting
.
AllowedPorts
,
fetchSetting
.
ApplyIPFilterForDomain
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"request reject: %v"
,
err
)
return
nil
,
fmt
.
Errorf
(
"request reject: %v"
,
err
)
}
}
...
...
service/user_notify.go
View file @
82163b4b
...
@@ -115,7 +115,7 @@ func sendBarkNotify(barkURL string, data dto.Notify) error {
...
@@ -115,7 +115,7 @@ func sendBarkNotify(barkURL string, data dto.Notify) error {
}
else
{
}
else
{
// SSRF防护:验证Bark URL(非Worker模式)
// SSRF防护:验证Bark URL(非Worker模式)
fetchSetting
:=
system_setting
.
GetFetchSetting
()
fetchSetting
:=
system_setting
.
GetFetchSetting
()
if
err
:=
common
.
ValidateURLWithFetchSetting
(
finalURL
,
fetchSetting
.
EnableSSRFProtection
,
fetchSetting
.
AllowPrivateIp
,
fetchSetting
.
DomainFilterMode
,
fetchSetting
.
IpFilterMode
,
fetchSetting
.
DomainList
,
fetchSetting
.
IpList
,
fetchSetting
.
AllowedPorts
);
err
!=
nil
{
if
err
:=
common
.
ValidateURLWithFetchSetting
(
finalURL
,
fetchSetting
.
EnableSSRFProtection
,
fetchSetting
.
AllowPrivateIp
,
fetchSetting
.
DomainFilterMode
,
fetchSetting
.
IpFilterMode
,
fetchSetting
.
DomainList
,
fetchSetting
.
IpList
,
fetchSetting
.
AllowedPorts
,
fetchSetting
.
ApplyIPFilterForDomain
);
err
!=
nil
{
return
fmt
.
Errorf
(
"request reject: %v"
,
err
)
return
fmt
.
Errorf
(
"request reject: %v"
,
err
)
}
}
...
...
service/webhook.go
View file @
82163b4b
...
@@ -89,7 +89,7 @@ func SendWebhookNotify(webhookURL string, secret string, data dto.Notify) error
...
@@ -89,7 +89,7 @@ func SendWebhookNotify(webhookURL string, secret string, data dto.Notify) error
}
else
{
}
else
{
// SSRF防护:验证Webhook URL(非Worker模式)
// SSRF防护:验证Webhook URL(非Worker模式)
fetchSetting
:=
system_setting
.
GetFetchSetting
()
fetchSetting
:=
system_setting
.
GetFetchSetting
()
if
err
:=
common
.
ValidateURLWithFetchSetting
(
webhookURL
,
fetchSetting
.
EnableSSRFProtection
,
fetchSetting
.
AllowPrivateIp
,
fetchSetting
.
DomainFilterMode
,
fetchSetting
.
IpFilterMode
,
fetchSetting
.
DomainList
,
fetchSetting
.
IpList
,
fetchSetting
.
AllowedPorts
);
err
!=
nil
{
if
err
:=
common
.
ValidateURLWithFetchSetting
(
webhookURL
,
fetchSetting
.
EnableSSRFProtection
,
fetchSetting
.
AllowPrivateIp
,
fetchSetting
.
DomainFilterMode
,
fetchSetting
.
IpFilterMode
,
fetchSetting
.
DomainList
,
fetchSetting
.
IpList
,
fetchSetting
.
AllowedPorts
,
fetchSetting
.
ApplyIPFilterForDomain
);
err
!=
nil
{
return
fmt
.
Errorf
(
"request reject: %v"
,
err
)
return
fmt
.
Errorf
(
"request reject: %v"
,
err
)
}
}
...
...
setting/system_setting/fetch_setting.go
View file @
82163b4b
...
@@ -10,6 +10,7 @@ type FetchSetting struct {
...
@@ -10,6 +10,7 @@ type FetchSetting struct {
DomainList
[]
string
`json:"domain_list"`
// domain format, e.g. example.com, *.example.com
DomainList
[]
string
`json:"domain_list"`
// domain format, e.g. example.com, *.example.com
IpList
[]
string
`json:"ip_list"`
// CIDR format
IpList
[]
string
`json:"ip_list"`
// CIDR format
AllowedPorts
[]
string
`json:"allowed_ports"`
// port range format, e.g. 80, 443, 8000-9000
AllowedPorts
[]
string
`json:"allowed_ports"`
// port range format, e.g. 80, 443, 8000-9000
ApplyIPFilterForDomain
bool
`json:"apply_ip_filter_for_domain"`
// 对域名启用IP过滤(实验性)
}
}
var
defaultFetchSetting
=
FetchSetting
{
var
defaultFetchSetting
=
FetchSetting
{
...
@@ -20,6 +21,7 @@ var defaultFetchSetting = FetchSetting{
...
@@ -20,6 +21,7 @@ var defaultFetchSetting = FetchSetting{
DomainList
:
[]
string
{},
DomainList
:
[]
string
{},
IpList
:
[]
string
{},
IpList
:
[]
string
{},
AllowedPorts
:
[]
string
{
"80"
,
"443"
,
"8080"
,
"8443"
},
AllowedPorts
:
[]
string
{
"80"
,
"443"
,
"8080"
,
"8443"
},
ApplyIPFilterForDomain
:
false
,
}
}
func
init
()
{
func
init
()
{
...
...
web/src/components/settings/SystemSetting.jsx
View file @
82163b4b
...
@@ -97,6 +97,7 @@ const SystemSetting = () => {
...
@@ -97,6 +97,7 @@ const SystemSetting = () => {
'fetch_setting.domain_list'
:
[],
'fetch_setting.domain_list'
:
[],
'fetch_setting.ip_list'
:
[],
'fetch_setting.ip_list'
:
[],
'fetch_setting.allowed_ports'
:
[],
'fetch_setting.allowed_ports'
:
[],
'fetch_setting.apply_ip_filter_for_domain'
:
false
,
});
});
const
[
originInputs
,
setOriginInputs
]
=
useState
({});
const
[
originInputs
,
setOriginInputs
]
=
useState
({});
...
@@ -132,6 +133,7 @@ const SystemSetting = () => {
...
@@ -132,6 +133,7 @@ const SystemSetting = () => {
case
'fetch_setting.enable_ssrf_protection'
:
case
'fetch_setting.enable_ssrf_protection'
:
case
'fetch_setting.domain_filter_mode'
:
case
'fetch_setting.domain_filter_mode'
:
case
'fetch_setting.ip_filter_mode'
:
case
'fetch_setting.ip_filter_mode'
:
case
'fetch_setting.apply_ip_filter_for_domain'
:
item
.
value
=
toBoolean
(
item
.
value
);
item
.
value
=
toBoolean
(
item
.
value
);
break
;
break
;
case
'fetch_setting.domain_list'
:
case
'fetch_setting.domain_list'
:
...
@@ -724,6 +726,17 @@ const SystemSetting = () => {
...
@@ -724,6 +726,17 @@ const SystemSetting = () => {
style=
{
{
marginTop
:
16
}
}
style=
{
{
marginTop
:
16
}
}
>
>
<
Col
xs=
{
24
}
sm=
{
24
}
md=
{
24
}
lg=
{
24
}
xl=
{
24
}
>
<
Col
xs=
{
24
}
sm=
{
24
}
md=
{
24
}
lg=
{
24
}
xl=
{
24
}
>
<
Banner
type=
'warning'
description=
{
t
(
'此功能为实验性选项,域名可能解析到多个 IPv4/IPv6 地址,若开启,请确保 IP 过滤列表覆盖这些地址,否则可能导致访问失败。'
)
}
style=
{
{
marginBottom
:
8
}
}
/>
<
Form
.
Checkbox
field=
'fetch_setting.apply_ip_filter_for_domain'
noLabel
onChange=
{
(
e
)
=>
handleCheckboxChange
(
'fetch_setting.apply_ip_filter_for_domain'
,
e
)
}
style=
{
{
marginBottom
:
8
}
}
>
{
t
(
'对域名启用 IP 过滤(实验性)'
)
}
</
Form
.
Checkbox
>
<
Text
strong
>
<
Text
strong
>
{
t
(
domainFilterMode
?
'域名白名单'
:
'域名黑名单'
)
}
{
t
(
domainFilterMode
?
'域名白名单'
:
'域名黑名单'
)
}
</
Text
>
</
Text
>
...
@@ -734,7 +747,8 @@ const SystemSetting = () => {
...
@@ -734,7 +747,8 @@ const SystemSetting = () => {
type=
'button'
type=
'button'
value=
{
domainFilterMode
?
'whitelist'
:
'blacklist'
}
value=
{
domainFilterMode
?
'whitelist'
:
'blacklist'
}
onChange=
{
(
val
)
=>
{
onChange=
{
(
val
)
=>
{
const
isWhitelist
=
val
===
'whitelist'
;
const
selected
=
val
&&
val
.
target
?
val
.
target
.
value
:
val
;
const
isWhitelist
=
selected
===
'whitelist'
;
setDomainFilterMode
(
isWhitelist
);
setDomainFilterMode
(
isWhitelist
);
setInputs
(
prev
=>
({
setInputs
(
prev
=>
({
...
prev
,
...
prev
,
...
@@ -780,7 +794,8 @@ const SystemSetting = () => {
...
@@ -780,7 +794,8 @@ const SystemSetting = () => {
type=
'button'
type=
'button'
value=
{
ipFilterMode
?
'whitelist'
:
'blacklist'
}
value=
{
ipFilterMode
?
'whitelist'
:
'blacklist'
}
onChange=
{
(
val
)
=>
{
onChange=
{
(
val
)
=>
{
const
isWhitelist
=
val
===
'whitelist'
;
const
selected
=
val
&&
val
.
target
?
val
.
target
.
value
:
val
;
const
isWhitelist
=
selected
===
'whitelist'
;
setIpFilterMode
(
isWhitelist
);
setIpFilterMode
(
isWhitelist
);
setInputs
(
prev
=>
({
setInputs
(
prev
=>
({
...
prev
,
...
prev
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment