mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-10-29 08:03:54 +00:00
feat(web): enable tld_dns_zone end-to-end from Web Console to MagicDNS (#2425)
This commit is contained in:
@@ -87,6 +87,7 @@ pub(crate) fn set_network_flags(result: &mut NetworkConfig, flags: FlagsPatch) {
|
||||
result.enable_udp_broadcast_relay = flags.enable_udp_broadcast_relay;
|
||||
result.disable_sym_hole_punching = flags.disable_sym_hole_punching;
|
||||
result.enable_magic_dns = flags.accept_dns;
|
||||
result.tld_dns_zone = flags.tld_dns_zone;
|
||||
result.mtu = flags.mtu.map(|mtu| mtu as i32);
|
||||
result.data_compress_algo = flags.data_compress_algo;
|
||||
result.encryption_algorithm = flags.encryption_algorithm;
|
||||
@@ -513,6 +514,7 @@ impl NetworkConfigExt for NetworkConfig {
|
||||
}
|
||||
}),
|
||||
accept_dns: self.enable_magic_dns,
|
||||
tld_dns_zone: self.tld_dns_zone.clone(),
|
||||
mtu: self
|
||||
.mtu
|
||||
.map(u32::try_from)
|
||||
@@ -929,6 +931,21 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn magic_dns_zone_round_trips_missing_default_and_custom_values() {
|
||||
for zone in [None, Some("et.net."), Some("nas.internal.")] {
|
||||
let input = NetworkConfig {
|
||||
tld_dns_zone: zone.map(str::to_owned),
|
||||
..standalone_config()
|
||||
};
|
||||
let config = input.gen_config().unwrap();
|
||||
let config = TomlConfigLoader::new_from_str(&config.dump()).unwrap();
|
||||
assert_eq!(config.get_flags().tld_dns_zone, zone.unwrap_or("et.net."));
|
||||
let output = NetworkConfig::new_from_config(&config).unwrap();
|
||||
assert_eq!(output.tld_dns_zone.as_deref(), zone);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vpn_portal_api_config_round_trips_through_toml_model() {
|
||||
let input = NetworkConfig {
|
||||
@@ -1045,6 +1062,22 @@ mod tests {
|
||||
assert!(config.get_vpn_portal_config().is_none());
|
||||
}
|
||||
|
||||
#[cfg(feature = "browser-config")]
|
||||
#[test]
|
||||
fn browser_merge_updates_and_clears_magic_dns_zone() {
|
||||
let original = "[flags]\ntld_dns_zone = \"old.internal.\"\n";
|
||||
for zone in [None, Some("et.net."), Some("nas.internal.")] {
|
||||
let input = NetworkConfig {
|
||||
tld_dns_zone: zone.map(str::to_owned),
|
||||
..standalone_config()
|
||||
};
|
||||
let merged = merge_network_config_toml(original, &input).unwrap();
|
||||
let output = TomlConfigLoader::new_from_str(&merged).unwrap();
|
||||
assert_eq!(output.get_flags().tld_dns_zone, zone.unwrap_or("et.net."));
|
||||
assert_eq!(output.get_flags_patch().tld_dns_zone.as_deref(), zone);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "browser-config")]
|
||||
#[test]
|
||||
fn browser_merge_reconciles_renamed_flags() {
|
||||
|
||||
@@ -50,6 +50,7 @@ message NetworkConfig {
|
||||
|
||||
optional bool use_smoltcp = 21;
|
||||
optional bool disable_ipv6 = 47;
|
||||
optional string tld_dns_zone = 73;
|
||||
optional bool enable_kcp_proxy = 22;
|
||||
optional bool disable_kcp_input = 23;
|
||||
optional bool disable_p2p = 24;
|
||||
|
||||
@@ -66,7 +66,7 @@ message Flags {
|
||||
bool disable_sym_hole_punching = 30 [(easytier.flag) = { default: "false" }];
|
||||
|
||||
// tld dns zone for magic dns
|
||||
string tld_dns_zone = 31 [(easytier.flag) = { default: "et.net." }];
|
||||
string tld_dns_zone = 31 [(easytier.flag) = { default: "et.net.", form: true }];
|
||||
|
||||
bool p2p_only = 32 [(easytier.flag) = { default: "false" }];
|
||||
|
||||
|
||||
@@ -168,6 +168,7 @@ function allFieldFixture() {
|
||||
mtu: 1280,
|
||||
mapped_listeners: ['tcp://127.0.0.1:13010'],
|
||||
enable_magic_dns: true,
|
||||
tld_dns_zone: 'nas.internal.',
|
||||
enable_private_mode: true,
|
||||
enable_quic_proxy: true,
|
||||
disable_quic_input: true,
|
||||
|
||||
@@ -387,6 +387,18 @@ function removeVpnPortalClient(index: number) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row gap-x-9 flex-wrap">
|
||||
<div class="flex flex-col gap-2 basis-5/12 grow">
|
||||
<div class="flex">
|
||||
<label for="tld_dns_zone">{{ t('tld_dns_zone') }}</label>
|
||||
<span class="pi pi-question-circle ml-2 self-center" v-tooltip="t('tld_dns_zone_help')"></span>
|
||||
</div>
|
||||
<InputText id="tld_dns_zone" :model-value="curNetwork.tld_dns_zone"
|
||||
@update:model-value="curNetwork.tld_dns_zone = $event?.trim() || undefined"
|
||||
aria-describedby="tld_dns_zone-help" :placeholder="t('tld_dns_zone_placeholder')" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row gap-x-9 flex-wrap">
|
||||
<div class="flex flex-col gap-2 basis-5/12 grow">
|
||||
<label for="hostname">{{ t('hostname') }}</label>
|
||||
|
||||
@@ -255,7 +255,11 @@ disable_sym_hole_punching_help: 禁用对称NAT的打洞(生日攻击),将
|
||||
enable_magic_dns: 启用魔法DNS
|
||||
enable_magic_dns_help: |
|
||||
启用魔法DNS,允许通过EasyTier的DNS服务器访问其他节点的虚拟IPv4地址, 如 node1.et.net。
|
||||
|
||||
tld_dns_zone: DNS域名后缀
|
||||
tld_dns_zone_help: |
|
||||
自定义魔法DNS的顶级域名(TLD)后缀。默认为 "et.net."。
|
||||
如需使用其他域名后缀,可改为 "et.internal." 或 "easytier.lan" 等。
|
||||
tld_dns_zone_placeholder: 例如 et.net.
|
||||
enable_private_mode: 启用私有模式
|
||||
enable_private_mode_help: |
|
||||
启用私有模式,则不允许使用了与本网络不相同的网络名称和密码的节点通过本节点进行握手或中转。
|
||||
|
||||
@@ -254,7 +254,11 @@ disable_sym_hole_punching_help: Disable special hole punching handling for symme
|
||||
enable_magic_dns: Enable Magic DNS
|
||||
enable_magic_dns_help: |
|
||||
Enable magic dns, all nodes in the network can access each other by domain name, e.g.: node1.et.net.
|
||||
|
||||
tld_dns_zone: DNS Zone TLD
|
||||
tld_dns_zone_help: |
|
||||
Custom top-level domain (TLD) zone for Magic DNS hostnames. Default is "et.net.".
|
||||
Change this if you need a different domain suffix, e.g. "et.internal." or "easytier.lan".
|
||||
tld_dns_zone_placeholder: e.g. et.net.
|
||||
enable_private_mode: Enable Private Mode
|
||||
enable_private_mode_help: |
|
||||
Enable private mode, nodes with different network names or passwords from this network are not allowed to perform handshake or relay through this node.
|
||||
|
||||
@@ -207,6 +207,7 @@ export function DEFAULT_NETWORK_CONFIG(): NetworkConfig {
|
||||
mtu: null,
|
||||
instance_recv_bps_limit: null,
|
||||
mapped_listeners: [],
|
||||
tld_dns_zone: 'et.net.',
|
||||
port_forwards: [],
|
||||
acl: emptyAcl(),
|
||||
}
|
||||
|
||||
@@ -416,6 +416,7 @@ describe('Config.vue network config projection', () => {
|
||||
expect(input(wrapper, '#no_tun').checked).toBe(true)
|
||||
|
||||
expect(input(wrapper, '#hostname').value).toBe('host-a')
|
||||
expect(input(wrapper, '#tld_dns_zone').value).toBe('et.net.')
|
||||
expect(input(wrapper, '#subnet-proxy').value).toBe('10.10.0.0/16,172.16.1.0/24')
|
||||
expect(input(wrapper, '#vpn_portal_wireguard_listen').value).toBe('0.0.0.0:22023')
|
||||
expect(input(wrapper, '#dev_name').value).toBe('tun-test')
|
||||
@@ -446,6 +447,7 @@ describe('Config.vue network config projection', () => {
|
||||
await wrapper.find('#no_tun').setValue(false)
|
||||
await wrapper.find('#disable_ipv6').setValue(false)
|
||||
await setInput(wrapper, '#hostname', 'host-edited')
|
||||
await setInput(wrapper, '#tld_dns_zone', 'nas.internal.')
|
||||
await setInput(wrapper, '#subnet-proxy', '10.7.0.0/16,172.17.0.0/16')
|
||||
await setInput(wrapper, '#vpn_portal_wireguard_listen', '[::]:23000')
|
||||
await setInput(wrapper, 'input[data-add-label="add_listener_url"]', 'tcp://0.0.0.0:13010')
|
||||
@@ -474,6 +476,7 @@ describe('Config.vue network config projection', () => {
|
||||
no_tun: false,
|
||||
disable_ipv6: false,
|
||||
hostname: 'host-edited',
|
||||
tld_dns_zone: 'nas.internal.',
|
||||
proxy_cidrs: ['10.7.0.0/16', '172.17.0.0/16'],
|
||||
vpn_portal_config: {
|
||||
wireguard_listen: '[::]:23000',
|
||||
@@ -509,6 +512,7 @@ describe('Config.vue network config projection', () => {
|
||||
network_secret: 'secret-edited',
|
||||
peer_urls: ['tcp://peer-x:11010', 'udp://peer-y:11010'],
|
||||
listener_urls: ['tcp://0.0.0.0:13010'],
|
||||
tld_dns_zone: 'nas.internal.',
|
||||
mtu: 1260,
|
||||
instance_recv_bps_limit: '9007199254740993',
|
||||
vpn_portal_config: {
|
||||
@@ -528,6 +532,9 @@ describe('Config.vue network config projection', () => {
|
||||
dst_port: 9090,
|
||||
}],
|
||||
})
|
||||
|
||||
await setInput(wrapper, '#tld_dns_zone', '')
|
||||
expect(toBackendNetworkConfig(curNetwork).tld_dns_zone).toBeUndefined()
|
||||
})
|
||||
|
||||
it('shows a flag the configuration does not state as the value the core resolves', async () => {
|
||||
|
||||
@@ -1086,6 +1086,7 @@ mod tests {
|
||||
assert_eq!(updated.disable_upnp, Some(true));
|
||||
assert_eq!(updated.disable_relay_data, Some(true));
|
||||
assert_eq!(updated.enable_magic_dns, Some(true));
|
||||
assert_eq!(updated.tld_dns_zone.as_deref(), Some("nas.internal."));
|
||||
assert_eq!(updated.enable_private_mode, Some(true));
|
||||
assert_eq!(updated.mtu, Some(1360));
|
||||
assert_eq!(
|
||||
@@ -1112,6 +1113,7 @@ mod tests {
|
||||
"relay_all_peer_rpc": false,
|
||||
"multi_thread": false,
|
||||
"disable_relay_data": false,
|
||||
"tld_dns_zone": "initial.internal.",
|
||||
"mtu": 1380
|
||||
})
|
||||
}
|
||||
@@ -1162,6 +1164,7 @@ mod tests {
|
||||
disable_upnp: Some(true),
|
||||
disable_relay_data: Some(true),
|
||||
enable_magic_dns: Some(true),
|
||||
tld_dns_zone: Some("nas.internal.".to_owned()),
|
||||
enable_private_mode: Some(true),
|
||||
mtu: Some(1360),
|
||||
data_compress_algo: Some(CompressionAlgoPb::Zstd as i32),
|
||||
@@ -1651,10 +1654,11 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
wait_for_runtime_config(&core_manager, instance_id, |config| {
|
||||
let initial = wait_for_runtime_config(&core_manager, instance_id, |config| {
|
||||
config.network_name.as_deref() == Some("managed-initial")
|
||||
})
|
||||
.await;
|
||||
assert_eq!(initial.tld_dns_zone.as_deref(), Some("initial.internal."));
|
||||
wait_for_applied_revision(&mgr, user_id, machine_id, "rev-initial").await;
|
||||
|
||||
// Runtime-only mutations do not change SQLite. Invalidate the Session
|
||||
@@ -1771,6 +1775,7 @@ mod tests {
|
||||
Some("managed-redelivered")
|
||||
);
|
||||
assert_eq!(redelivered.enable_kcp_proxy, Some(true));
|
||||
assert_eq!(redelivered.tld_dns_zone, None);
|
||||
assert_eq!(redelivered.instance_recv_bps_limit, Some(654321));
|
||||
assert_eq!(
|
||||
core_manager.config_source(instance_id),
|
||||
@@ -1806,6 +1811,7 @@ mod tests {
|
||||
Some("managed-redelivered")
|
||||
);
|
||||
assert_eq!(replayed.enable_kcp_proxy, Some(true));
|
||||
assert_eq!(replayed.tld_dns_zone, None);
|
||||
assert_eq!(replayed.instance_recv_bps_limit, Some(654321));
|
||||
|
||||
webhook_server.abort();
|
||||
|
||||
@@ -730,6 +730,26 @@ mod tests {
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn magic_dns_zone_change_requires_recreate() {
|
||||
let current = config_with_port_forwards(Vec::new());
|
||||
let mut desired = current.clone();
|
||||
desired.tld_dns_zone = Some("et.net.".to_owned());
|
||||
let action =
|
||||
prepare_web_source_runtime_reconcile_from_current(¤t, desired.clone(), false)
|
||||
.unwrap();
|
||||
assert!(matches!(action, RuntimeReconcileAction::Unchanged(_)));
|
||||
|
||||
desired.tld_dns_zone = Some("nas.internal.".to_owned());
|
||||
let action =
|
||||
prepare_web_source_runtime_reconcile_from_current(¤t, desired, false).unwrap();
|
||||
let RuntimeReconcileAction::Run { config, overwrite } = action else {
|
||||
panic!("changing the DNS zone must recreate the instance");
|
||||
};
|
||||
assert!(overwrite);
|
||||
assert_eq!(config.tld_dns_zone.as_deref(), Some("nas.internal."));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vpn_portal_client_changes_produce_hot_patches() {
|
||||
let current = config_with_vpn_portal(
|
||||
|
||||
Reference in New Issue
Block a user