diff --git a/frontend/src/pages/xray/OutboundFormModal.new.tsx b/frontend/src/pages/xray/OutboundFormModal.new.tsx
index 9eb42cb8..a4ab1232 100644
--- a/frontend/src/pages/xray/OutboundFormModal.new.tsx
+++ b/frontend/src/pages/xray/OutboundFormModal.new.tsx
@@ -30,7 +30,10 @@ import {
type OutboundFormValues,
} from '@/schemas/forms/outbound-form';
import {
+ DNSRuleActions,
+ OutboundDomainStrategies,
OutboundProtocols as Protocols,
+ SNIFFING_OPTION,
TLS_FLOW_CONTROL,
USERS_SECURITY,
WireguardDomainStrategy,
@@ -366,6 +369,389 @@ export default function OutboundFormModalNew({
)}
+ {protocol === 'dns' && (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {(fields, { add, remove }) => (
+ <>
+
+ }
+ onClick={() => add({ action: 'direct', qtype: '', domain: '' })}
+ />
+
+ {fields.map((field, index) => (
+
+
+
+ Rule {index + 1}
+ remove(field.name)}
+ />
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+ >
+ )}
+
+ >
+ )}
+
+ {protocol === 'freedom' && (
+ <>
+
+
+
+
+
+
+
+ {() => {
+ const fragment = (form.getFieldValue(['settings', 'fragment']) ?? {}) as {
+ packets?: string;
+ length?: string;
+ interval?: string;
+ maxSplit?: string;
+ };
+ const enabled = !!(fragment.length || fragment.interval || fragment.maxSplit);
+ return (
+ <>
+
+ {
+ form.setFieldValue(
+ ['settings', 'fragment'],
+ checked
+ ? {
+ packets: 'tlshello',
+ length: '100-200',
+ interval: '10-20',
+ maxSplit: '300-400',
+ }
+ : { packets: '', length: '', interval: '', maxSplit: '' },
+ );
+ }}
+ />
+
+ {enabled && (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )}
+ >
+ );
+ }}
+
+
+
+ {(fields, { add, remove }) => (
+ <>
+
+ 0}
+ onChange={(checked) => {
+ if (checked) {
+ add({
+ type: 'rand',
+ packet: '10-20',
+ delay: '10-16',
+ applyTo: 'ip',
+ });
+ } else {
+ // remove() with no arg is not supported;
+ // walk fields in reverse and drop each.
+ for (let i = fields.length - 1; i >= 0; i--) {
+ remove(fields[i].name);
+ }
+ }
+ }}
+ />
+ {fields.length > 0 && (
+ }
+ onClick={() =>
+ add({
+ type: 'rand',
+ packet: '10-20',
+ delay: '10-16',
+ applyTo: 'ip',
+ })
+ }
+ />
+ )}
+
+ {fields.map((field, index) => (
+
+
+
+ Noise {index + 1}
+ {fields.length > 1 && (
+ remove(field.name)}
+ />
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+ >
+ )}
+
+
+
+ {(fields, { add, remove }) => (
+ <>
+
+ }
+ onClick={() =>
+ add({
+ action: 'allow',
+ network: '',
+ port: '',
+ ip: [],
+ blockDelay: '',
+ })
+ }
+ />
+
+ Override Xray's default private-IP block
+
+
+ {fields.map((field, index) => (
+
+
+
+ Rule {index + 1}
+ remove(field.name)}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {() => {
+ const ruleAction = form.getFieldValue([
+ 'settings',
+ 'finalRules',
+ field.name,
+ 'action',
+ ]);
+ if (ruleAction !== 'block') return null;
+ return (
+
+
+
+ );
+ }}
+
+
+ ))}
+ >
+ )}
+
+ >
+ )}
+
+ {protocol === 'vless' && (
+
+ {() => {
+ const reverseTag = form.getFieldValue(['settings', 'reverseTag']);
+ if (!reverseTag) return null;
+ const sniff = (form.getFieldValue(['settings', 'reverseSniffing']) ?? {}) as {
+ enabled?: boolean;
+ };
+ return (
+ <>
+
+
+
+ {sniff.enabled && (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )}
+ >
+ );
+ }}
+
+ )}
+
{protocol === 'wireguard' && (
<>