mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-11 07:06:06 +00:00
Add encrypted DNS presets (#5837)
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
.preset-warning {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.preset-list {
|
||||
border: 1px solid var(--ant-color-border-secondary);
|
||||
border-radius: 8px;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Modal, Space, Tag } from 'antd';
|
||||
import { Alert, Button, Modal, Space, Tag } from 'antd';
|
||||
import './DnsPresetsModal.css';
|
||||
|
||||
interface DnsPresetsModalProps {
|
||||
@@ -8,34 +8,69 @@ interface DnsPresetsModalProps {
|
||||
onInstall: (servers: string[]) => void;
|
||||
}
|
||||
|
||||
const PRESETS: { name: string; family: boolean; data: string[] }[] = [
|
||||
export const PRESETS: { name: string; tags: string[]; data: string[] }[] = [
|
||||
{
|
||||
name: 'Google DNS',
|
||||
family: false,
|
||||
tags: ['UDP'],
|
||||
data: ['8.8.8.8', '8.8.4.4', '2001:4860:4860::8888', '2001:4860:4860::8844'],
|
||||
},
|
||||
{
|
||||
name: 'Cloudflare DNS',
|
||||
family: false,
|
||||
tags: ['UDP'],
|
||||
data: ['1.1.1.1', '1.0.0.1', '2606:4700:4700::1111', '2606:4700:4700::1001'],
|
||||
},
|
||||
{
|
||||
name: 'AdGuard DNS',
|
||||
family: false,
|
||||
tags: ['UDP'],
|
||||
data: ['94.140.14.14', '94.140.15.15', '2a10:50c0::ad1:ff', '2a10:50c0::ad2:ff'],
|
||||
},
|
||||
{
|
||||
name: 'AdGuard Family DNS',
|
||||
family: true,
|
||||
tags: ['UDP', 'Family'],
|
||||
data: ['94.140.14.15', '94.140.15.16', '2a10:50c0::bad1:ff', '2a10:50c0::bad2:ff'],
|
||||
},
|
||||
{
|
||||
name: 'Cloudflare Family DNS',
|
||||
family: true,
|
||||
tags: ['UDP', 'Family'],
|
||||
data: ['1.1.1.3', '1.0.0.3', '2606:4700:4700::1113', '2606:4700:4700::1003'],
|
||||
},
|
||||
{
|
||||
name: 'Cloudflare DoH',
|
||||
tags: ['DoH'],
|
||||
data: ['https://cloudflare-dns.com/dns-query'],
|
||||
},
|
||||
{
|
||||
name: 'Google DoH',
|
||||
tags: ['DoH'],
|
||||
data: ['https://dns.google/dns-query'],
|
||||
},
|
||||
{
|
||||
name: 'Quad9 Secure DoH',
|
||||
tags: ['DoH', 'Malware'],
|
||||
data: ['https://dns.quad9.net/dns-query'],
|
||||
},
|
||||
{
|
||||
name: 'AdGuard DoH + DoQ',
|
||||
tags: ['DoH', 'DoQ', 'Ads'],
|
||||
data: ['https://dns.adguard-dns.com/dns-query', 'quic+local://dns.adguard-dns.com'],
|
||||
},
|
||||
{
|
||||
name: 'Control D Ads DoH + DoQ',
|
||||
tags: ['DoH', 'DoQ', 'Ads'],
|
||||
data: ['https://freedns.controld.com/p2', 'quic+local://p2.freedns.controld.com'],
|
||||
},
|
||||
{
|
||||
name: 'Control D Family DoH + DoQ',
|
||||
tags: ['DoH', 'DoQ', 'Family'],
|
||||
data: ['https://freedns.controld.com/p4', 'quic+local://p4.freedns.controld.com'],
|
||||
},
|
||||
];
|
||||
|
||||
function tagLabel(tag: string, t: (key: string) => string): string {
|
||||
if (tag === 'Family') return t('pages.xray.dns.dnsPresetFamily');
|
||||
return tag;
|
||||
}
|
||||
|
||||
export default function DnsPresetsModal({ open, onClose, onInstall }: DnsPresetsModalProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -47,13 +82,21 @@ export default function DnsPresetsModal({ open, onClose, onInstall }: DnsPresets
|
||||
mask={{ closable: false }}
|
||||
onCancel={onClose}
|
||||
>
|
||||
<Alert
|
||||
type="warning"
|
||||
showIcon
|
||||
className="preset-warning"
|
||||
message={t('pages.xray.dns.dnsLeakWarning')}
|
||||
/>
|
||||
<div className="preset-list">
|
||||
{PRESETS.map((preset) => (
|
||||
<div key={preset.name} className="preset-row">
|
||||
<Space size="small" align="center">
|
||||
<Tag color={preset.family ? 'purple' : 'green'}>
|
||||
{preset.family ? t('pages.xray.dns.dnsPresetFamily') : 'DNS'}
|
||||
</Tag>
|
||||
{preset.tags.map((tag) => (
|
||||
<Tag key={tag} color={tag === 'Family' ? 'purple' : tag === 'UDP' ? 'orange' : 'green'}>
|
||||
{tagLabel(tag, t)}
|
||||
</Tag>
|
||||
))}
|
||||
<span className="preset-name">{preset.name}</span>
|
||||
</Space>
|
||||
<Button type="primary" size="small" onClick={() => onInstall([...preset.data])}>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Empty, Input, InputNumber, Modal, Select, Space, Switch, Table, Tabs } from 'antd';
|
||||
import { Alert, Button, Empty, Input, InputNumber, Modal, Select, Space, Switch, Table, Tabs } from 'antd';
|
||||
import {
|
||||
DatabaseOutlined,
|
||||
DeleteOutlined,
|
||||
@@ -237,6 +237,12 @@ export default function DnsTab({ templateSettings, setTemplateSettings }: DnsTab
|
||||
/>
|
||||
{dnsEnabled && (
|
||||
<>
|
||||
<Alert
|
||||
type="warning"
|
||||
showIcon
|
||||
message={t('pages.xray.dns.dnsLeakWarning')}
|
||||
style={{ marginBottom: 12 }}
|
||||
/>
|
||||
<SettingListItem
|
||||
paddings="small"
|
||||
title={t('pages.xray.dns.tag')}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { PRESETS } from '@/pages/xray/dns/DnsPresetsModal';
|
||||
import { DnsObjectSchema, DnsServerObjectSchema } from '@/schemas/dns';
|
||||
|
||||
describe('DNS presets', () => {
|
||||
it('include encrypted presets accepted by xray DNS config', () => {
|
||||
const servers = PRESETS.flatMap((preset) => preset.data);
|
||||
|
||||
expect(servers).toContain('https://freedns.controld.com/p2');
|
||||
expect(servers).toContain('quic+local://p2.freedns.controld.com');
|
||||
expect(servers).toContain('https://dns.google/dns-query');
|
||||
expect(servers.every((server) => !server.startsWith('tls://'))).toBe(true);
|
||||
expect(DnsObjectSchema.parse({ servers }).servers).toEqual(servers);
|
||||
for (const server of servers) {
|
||||
expect(DnsServerObjectSchema.parse({ address: server }).address).toBe(server);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user