fix(security): configure trusted Fake-IP DNS hosts

This commit is contained in:
elky
2026-09-05 14:05:07 +08:00
parent f69b770f5e
commit e15ea0d5d3
8 changed files with 371 additions and 38 deletions
@@ -50,12 +50,14 @@
<ProxyConfigSection
id="section-proxy"
:proxy-node-id="systemConfig.system_proxy_node_id"
:extra-trusted-dns-hosts-str="extraTrustedDnsHostsStr"
:online-nodes="proxyNodesStore.onlineNodes"
:all-nodes="proxyNodesStore.nodes"
:loading="systemConfigLoading || proxyConfigLoading"
:has-changes="hasProxyConfigChanges"
@save="saveProxyConfig"
@update:proxy-node-id="systemConfig.system_proxy_node_id = $event"
@update:extra-trusted-dns-hosts-str="extraTrustedDnsHostsStr = $event"
/>
<!-- 基础配置 -->
@@ -351,6 +353,7 @@ const {
hasCleanupConfigChanges,
sensitiveHeadersStr,
turnstileAllowedHostnamesStr,
extraTrustedDnsHostsStr,
loadSystemConfig,
loadSystemVersion,
saveSiteInfo,
@@ -40,6 +40,25 @@
对未单独配置代理的提供商生效,覆盖大模型 API 请求、余额查询、OAuth 刷新等。不影响系统内部接口。
</p>
</div>
<div class="mt-6 max-w-2xl border-t pt-5">
<Label
for="extra-trusted-dns-hosts"
class="block text-sm font-medium"
>
额外可信 Fake-IP 域名
</Label>
<Textarea
id="extra-trusted-dns-hosts"
:model-value="extraTrustedDnsHostsStr"
rows="4"
class="mt-1"
placeholder="api.example.com\nmodels.example.com"
@update:model-value="$emit('update:extraTrustedDnsHostsStr', String($event || ''))"
/>
<p class="mt-1 text-xs text-muted-foreground">
每行填写一个精确 hostname;不支持通配符、后缀、端口、路径或 IP。仅允许这些域名返回 198.18.0.0/15 Fake-IP,内置提供商域名不受影响。
</p>
</div>
</CardSection>
</template>
@@ -47,6 +66,7 @@
import { computed } from 'vue'
import Button from '@/components/ui/button.vue'
import Label from '@/components/ui/label.vue'
import Textarea from '@/components/ui/textarea.vue'
import Select from '@/components/ui/select.vue'
import SelectTrigger from '@/components/ui/select-trigger.vue'
import SelectValue from '@/components/ui/select-value.vue'
@@ -64,6 +84,7 @@ interface ProxyNode {
const props = defineProps<{
proxyNodeId: string | null
extraTrustedDnsHostsStr: string
onlineNodes: ProxyNode[]
allNodes: ProxyNode[]
loading: boolean
@@ -73,6 +94,7 @@ const props = defineProps<{
defineEmits<{
save: []
'update:proxyNodeId': [value: string | null]
'update:extraTrustedDnsHostsStr': [value: string]
}>()
const selectableNodes = computed(() => {
@@ -80,4 +80,31 @@ describe('useSystemConfig', () => {
expect(state.systemConfig.value).not.toHaveProperty('max_request_body_size')
expect(state.systemConfig.value).not.toHaveProperty('max_response_body_size')
})
it('loads and saves the extra trusted Fake-IP DNS hosts with proxy settings', async () => {
getAllSystemConfigsMock.mockResolvedValue([
{ key: 'system_proxy_node_id', value: 'node-1' },
{ key: 'execution_extra_trusted_dns_hosts', value: ['custom.example.com'] },
])
updateSystemConfigMock.mockResolvedValue(undefined)
const state = useSystemConfig()
await state.loadSystemConfig()
expect(state.extraTrustedDnsHostsStr.value).toBe('custom.example.com')
state.extraTrustedDnsHostsStr.value = 'api.example.com\nmodels.example.com'
expect(state.systemConfig.value.execution_extra_trusted_dns_hosts).toEqual([
'api.example.com',
'models.example.com',
])
await state.saveProxyConfig()
expect(updateSystemConfigMock).toHaveBeenCalledWith(
'execution_extra_trusted_dns_hosts',
['api.example.com', 'models.example.com'],
'执行运行时额外可信 Fake-IP 域名'
)
expect(state.hasProxyConfigChanges.value).toBe(false)
})
})
@@ -10,6 +10,7 @@ export interface SystemConfig {
site_subtitle: string
// 网络代理
system_proxy_node_id: string | null
execution_extra_trusted_dns_hosts: string[]
// 基础配置
default_user_initial_gift_usd: number
rate_limit_per_minute: number
@@ -61,6 +62,7 @@ const CONFIG_KEYS = [
'site_subtitle',
// 网络代理
'system_proxy_node_id',
'execution_extra_trusted_dns_hosts',
// 基础配置
'default_user_initial_gift_usd',
'rate_limit_per_minute',
@@ -112,6 +114,7 @@ function createDefaultConfig(): SystemConfig {
site_subtitle: 'AI Gateway',
// 网络代理
system_proxy_node_id: null,
execution_extra_trusted_dns_hosts: [],
// 基础配置
default_user_initial_gift_usd: 10.0,
rate_limit_per_minute: 0,
@@ -188,6 +191,8 @@ export function useSystemConfig() {
if (systemConfigLoading.value) return false
if (!originalConfig.value) return false
return systemConfig.value.system_proxy_node_id !== originalConfig.value.system_proxy_node_id
|| JSON.stringify(systemConfig.value.execution_extra_trusted_dns_hosts) !==
JSON.stringify(originalConfig.value.execution_extra_trusted_dns_hosts)
})
const hasBasicConfigChanges = computed(() => {
@@ -278,6 +283,16 @@ export function useSystemConfig() {
},
})
const extraTrustedDnsHostsStr = computed({
get: () => systemConfig.value.execution_extra_trusted_dns_hosts.join('\n'),
set: (val: string) => {
systemConfig.value.execution_extra_trusted_dns_hosts = val
.split(/[\n,]/)
.map((s) => s.trim().toLowerCase().replace(/\.$/, ''))
.filter((s) => s.length > 0)
},
})
// 加载配置
async function loadSystemConfig() {
systemConfigLoading.value = true
@@ -355,13 +370,23 @@ export function useSystemConfig() {
async function saveProxyConfig() {
proxyConfigLoading.value = true
try {
await adminApi.updateSystemConfig(
'system_proxy_node_id',
systemConfig.value.system_proxy_node_id || null,
'系统默认代理节点 ID'
)
await Promise.all([
adminApi.updateSystemConfig(
'system_proxy_node_id',
systemConfig.value.system_proxy_node_id || null,
'系统默认代理节点 ID'
),
adminApi.updateSystemConfig(
'execution_extra_trusted_dns_hosts',
systemConfig.value.execution_extra_trusted_dns_hosts,
'执行运行时额外可信 Fake-IP 域名'
),
])
if (originalConfig.value) {
originalConfig.value.system_proxy_node_id = systemConfig.value.system_proxy_node_id
originalConfig.value.execution_extra_trusted_dns_hosts = [
...systemConfig.value.execution_extra_trusted_dns_hosts,
]
}
success('网络代理配置已保存')
} catch (err) {
@@ -716,6 +741,7 @@ export function useSystemConfig() {
// 计算属性
sensitiveHeadersStr,
turnstileAllowedHostnamesStr,
extraTrustedDnsHostsStr,
// 加载函数
loadSystemConfig,
loadSystemVersion,