mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-13 01:14:59 +03:00
feat(inbounds): TUN adapter type and auto-system options
xray-core 26.9 added three TUN settings the inbound form could not set: - desc, the tunnel type a new Wintun adapter is created with on Windows. The settings schema did not list it, so the parse stripped it and a value entered as JSON vanished on the next save; - autoSystemDnsToGateway (Linux), which points systemd-resolved at the TUN gateway; - autoSystemWfpBlockLeak (Windows), whose dns / misconfigtun filters keep traffic from leaking past the TUN. The tooltips name the platform each one acts on and what it needs, since the core refuses to build or start the TUN otherwise.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Form, Input, InputNumber, Space, Tooltip } from 'antd';
|
||||
import { Button, Form, Input, InputNumber, Select, Space, Switch, Tooltip } from 'antd';
|
||||
import { MinusOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import { useFieldArray, useFormContext } from 'react-hook-form';
|
||||
|
||||
@@ -35,6 +35,12 @@ function StringList({ name, label, placeholder }: StringListProps) {
|
||||
);
|
||||
}
|
||||
|
||||
// xray-core 26.9.30 accepts exactly these autoSystemWfpBlockLeak values.
|
||||
const WFP_BLOCK_LEAK_OPTIONS = [
|
||||
{ value: 'dns', label: 'dns' },
|
||||
{ value: 'misconfigtun', label: 'misconfigtun' },
|
||||
];
|
||||
|
||||
export default function TunFields() {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
@@ -42,6 +48,13 @@ export default function TunFields() {
|
||||
<FormField name={['settings', 'name']} label={t('pages.inbounds.info.interfaceName')}>
|
||||
<Input placeholder="xray0" />
|
||||
</FormField>
|
||||
<FormField
|
||||
name={['settings', 'desc']}
|
||||
label={t('pages.inbounds.form.tunDesc')}
|
||||
tooltip={t('pages.inbounds.form.tunDescTooltip')}
|
||||
>
|
||||
<Input id="tun-desc" placeholder="Wintun" />
|
||||
</FormField>
|
||||
<FormField name={['settings', 'mtu']} label="MTU">
|
||||
<InputNumber min={0} />
|
||||
</FormField>
|
||||
@@ -77,6 +90,26 @@ export default function TunFields() {
|
||||
>
|
||||
<Input placeholder="auto" />
|
||||
</FormField>
|
||||
<FormField
|
||||
name={['settings', 'autoSystemDnsToGateway']}
|
||||
label={t('pages.inbounds.form.autoSystemDnsToGateway')}
|
||||
tooltip={t('pages.inbounds.form.autoSystemDnsToGatewayTooltip')}
|
||||
valueProp="checked"
|
||||
>
|
||||
<Switch id="tun-auto-dns-gateway" />
|
||||
</FormField>
|
||||
<FormField
|
||||
name={['settings', 'autoSystemWfpBlockLeak']}
|
||||
label={t('pages.inbounds.form.autoSystemWfpBlockLeak')}
|
||||
tooltip={t('pages.inbounds.form.autoSystemWfpBlockLeakTooltip')}
|
||||
>
|
||||
<Select
|
||||
id="tun-wfp-block-leak"
|
||||
mode="multiple"
|
||||
allowClear
|
||||
options={WFP_BLOCK_LEAK_OPTIONS}
|
||||
/>
|
||||
</FormField>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import { z } from 'zod';
|
||||
|
||||
export const TunInboundSettingsSchema = z.object({
|
||||
name: z.string().default('xray0'),
|
||||
// Windows: the tunnel type a new Wintun adapter is created with (core default Wintun).
|
||||
desc: z.string().optional(),
|
||||
mtu: z.number().int().min(0).default(1500),
|
||||
gateway: z.array(z.string()).default([]),
|
||||
dns: z.array(z.string()).default([]),
|
||||
|
||||
@@ -467,6 +467,49 @@ describe('InboundFormModal', () => {
|
||||
expect(JSON.stringify(finalmask.udp ?? [])).not.toContain('udphop');
|
||||
});
|
||||
|
||||
// xray-core 26.9: the Wintun adapter type (desc) and the TUN auto-system leak guards.
|
||||
it('saves the TUN adapter type and auto-system options set in the form', async () => {
|
||||
const post = vi.mocked(HttpUtil.post);
|
||||
post.mockClear();
|
||||
const tun = new DBInbound({
|
||||
id: 44,
|
||||
port: 0,
|
||||
listen: '',
|
||||
protocol: 'tun',
|
||||
remark: 'tun',
|
||||
enable: true,
|
||||
settings: {
|
||||
name: 'xray0',
|
||||
mtu: 1500,
|
||||
gateway: ['10.0.0.1/16'],
|
||||
dns: ['1.1.1.1'],
|
||||
userLevel: 0,
|
||||
autoSystemRoutingTable: ['0.0.0.0/0'],
|
||||
autoOutboundsInterface: 'auto',
|
||||
},
|
||||
streamSettings: {},
|
||||
sniffing: { enabled: false },
|
||||
nodeId: null,
|
||||
shareAddrStrategy: 'listen',
|
||||
shareAddr: '',
|
||||
});
|
||||
renderCloneLikeEdit(tun);
|
||||
|
||||
fireEvent.change(document.getElementById('tun-desc')!, { target: { value: 'MyTun' } });
|
||||
fireEvent.click(document.getElementById('tun-auto-dns-gateway')!);
|
||||
chooseSelectOption('tun-wfp-block-leak', 'dns');
|
||||
fireEvent.click(primaryButton());
|
||||
|
||||
const isUpdate = ([url]: unknown[]) => url === '/panel/api/inbounds/update/44';
|
||||
await waitFor(() => expect(post.mock.calls.some(isUpdate)).toBe(true));
|
||||
const payload = post.mock.calls.find(isUpdate)![1] as { settings: string };
|
||||
expect(JSON.parse(payload.settings)).toMatchObject({
|
||||
desc: 'MyTun',
|
||||
autoSystemDnsToGateway: true,
|
||||
autoSystemWfpBlockLeak: ['dns'],
|
||||
});
|
||||
});
|
||||
|
||||
// Clients and enable change through their own endpoints; the server keeps the
|
||||
// stored ones, so the edit form must neither send nor validate its stale copy.
|
||||
it('edit save neither sends nor validates the clients it loaded', async () => {
|
||||
|
||||
@@ -60,12 +60,13 @@ describe('inboundFromDb', () => {
|
||||
|
||||
// The settings parse strips keys the schema does not list, so a TUN option xray-core
|
||||
// 26.9.30 added and an admin entered as JSON would vanish on the next form save.
|
||||
it('keeps the TUN options xray-core 26.9.30 added', () => {
|
||||
it('keeps the TUN options xray-core 26.9 added', () => {
|
||||
const inbound = inboundFromDb({
|
||||
...BASE_DB_FIELDS,
|
||||
protocol: 'tun',
|
||||
settings: {
|
||||
name: 'xray0',
|
||||
desc: 'MyTun',
|
||||
gateway: ['10.0.0.1/16'],
|
||||
autoSystemDnsToGateway: true,
|
||||
autoSystemWfpBlockLeak: ['dns', 'misconfigtun'],
|
||||
@@ -73,6 +74,7 @@ describe('inboundFromDb', () => {
|
||||
streamSettings: '',
|
||||
});
|
||||
expect(inbound.settings).toMatchObject({
|
||||
desc: 'MyTun',
|
||||
autoSystemDnsToGateway: true,
|
||||
autoSystemWfpBlockLeak: ['dns', 'misconfigtun'],
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user