diff --git a/rust/connlib/tunnel/proptest-regressions/tests.txt b/rust/connlib/tunnel/proptest-regressions/tests.txt index 9d96f6df1..fb277b83b 100644 --- a/rust/connlib/tunnel/proptest-regressions/tests.txt +++ b/rust/connlib/tunnel/proptest-regressions/tests.txt @@ -63,3 +63,5 @@ cc 6f00b4fe571ce46735ae49e5729677e7f098b354ccf1449a14b77ee46a564c40 # shrinks to cc ffad6338bc4f13a8bd70b8c47149cc9e246fbaafbb2ea5ef8dfec15d88dff13f # shrinks to (initial_state, transitions, seen_counter) = (ReferenceState { client: Host { inner: RefClient { id: 0, key: PrivateKey("0000000000000000000000000000000000000000000000000000000000000000"), known_hosts: {}, tunnel_ip4: 100.64.0.1, tunnel_ip6: fd00:2021:1111::, system_dns_resolvers: [0.0.0.0], upstream_dns_resolvers: [], internet_resource: None, cidr_resources: {}, dns_resources: {}, dns_records: {}, connected_internet_resources: false, connected_cidr_resources: {}, connected_dns_resources: {}, expected_icmp_handshakes: {}, expected_dns_handshakes: [] }, ip4: Some(203.0.113.1), ip6: Some(2001:db80::), old_ports: {0}, default_port: 1, allocated_ports: {(1, V6), (1, V4)}, latency: 10ms, inbox: BufferedTransmits { inner: [] } }, gateways: {70703E654B89BF37D9F665: Host { inner: RefGateway { key: PrivateKey("7e352e134c81e86246e97333743052a446a2b8bd61ada00eb9826c79c2e7fa7d") }, ip4: Some(203.0.113.24), ip6: Some(2001:db80::35), old_ports: {0}, default_port: 14062, allocated_ports: {(14062, V6), (14062, V4)}, latency: 44ms, inbox: BufferedTransmits { inner: [] } }}, relays: {FB6E92EEDC915C5FB99078A9F36D03FA: Host { inner: 945565326848173624, ip4: Some(203.0.113.51), ip6: Some(2001:db80::10), old_ports: {0}, default_port: 3478, allocated_ports: {(3478, V6), (3478, V4)}, latency: 16ms, inbox: BufferedTransmits { inner: [] } }}, portal: StubPortal { gateways_by_site: {68B4BC644DE5F0F249FFB3016558099C: {70703E654B89BF37D9F665}}, sites_by_resource: {E17A77901A12F5E1ACC7BAB87829629C: DAB747DEB17138948C05A10E4DA40C69, 1FB725D749FE974ECBB1B06514F9EFCF: 68B4BC644DE5F0F249FFB3016558099C, D87B3DCFB028B941319CC6B670BC3920: 68B4BC644DE5F0F249FFB3016558099C, 35AC75045C1DD15D321158CB273570E2: DAB747DEB17138948C05A10E4DA40C69, 6261B9E0DFC219EA3FEFE7CA795C4759: DAB747DEB17138948C05A10E4DA40C69, F3AFB1503FFB5275E247B40D338981D7: 68B4BC644DE5F0F249FFB3016558099C, 9CF5652148850FE73BF66F6B4929DFC0: 68B4BC644DE5F0F249FFB3016558099C, 609B5D37B3AF65B5452679AF48D43396: DAB747DEB17138948C05A10E4DA40C69}, cidr_resources: {D87B3DCFB028B941319CC6B670BC3920: ResourceDescriptionCidr { id: D87B3DCFB028B941319CC6B670BC3920, address: V6(Ipv6Network { network_address: 7cea:aeb8:76fb:cff7:ca36:7429:4919:dcc0, netmask: 122 }), name: "quaqav", address_description: None, sites: [Site { id: 68B4BC644DE5F0F249FFB3016558099C, name: "qfvlo" }] }, 9CF5652148850FE73BF66F6B4929DFC0: ResourceDescriptionCidr { id: 9CF5652148850FE73BF66F6B4929DFC0, address: V4(Ipv4Network { network_address: 127.0.0.0, netmask: 26 }), name: "dcyfvatbt", address_description: Some("hliktug"), sites: [Site { id: 68B4BC644DE5F0F249FFB3016558099C, name: "qfvlo" }] }, 6261B9E0DFC219EA3FEFE7CA795C4759: ResourceDescriptionCidr { id: 6261B9E0DFC219EA3FEFE7CA795C4759, address: V6(Ipv6Network { network_address: 985e:eec2:a3eb:b2b6:57ba:15e3:8d34:2e40, netmask: 124 }), name: "rdrelb", address_description: None, sites: [Site { id: DAB747DEB17138948C05A10E4DA40C69, name: "idxdtvzjsl" }] }, E17A77901A12F5E1ACC7BAB87829629C: ResourceDescriptionCidr { id: E17A77901A12F5E1ACC7BAB87829629C, address: V6(Ipv6Network { network_address: ::ffff:96.93.142.184, netmask: 126 }), name: "nhtzwf", address_description: None, sites: [Site { id: DAB747DEB17138948C05A10E4DA40C69, name: "idxdtvzjsl" }] }}, dns_resources: {F3AFB1503FFB5275E247B40D338981D7: ResourceDescriptionDns { id: F3AFB1503FFB5275E247B40D338981D7, address: "?.rfgc.emlk.ztx", name: "wnmphidrw", address_description: None, sites: [Site { id: 68B4BC644DE5F0F249FFB3016558099C, name: "qfvlo" }] }, 35AC75045C1DD15D321158CB273570E2: ResourceDescriptionDns { id: 35AC75045C1DD15D321158CB273570E2, address: "*.feluz.pygfb", name: "rpncz", address_description: Some("jwlrlwywdb"), sites: [Site { id: DAB747DEB17138948C05A10E4DA40C69, name: "idxdtvzjsl" }] }, 609B5D37B3AF65B5452679AF48D43396: ResourceDescriptionDns { id: 609B5D37B3AF65B5452679AF48D43396, address: "*.ruwzl.msjhe", name: "rezmo", address_description: None, sites: [Site { id: DAB747DEB17138948C05A10E4DA40C69, name: "idxdtvzjsl" }] }}, internet_resource: ResourceDescriptionInternet { id: 1FB725D749FE974ECBB1B06514F9EFCF, sites: [Site { id: 68B4BC644DE5F0F249FFB3016558099C, name: "qfvlo" }] }, gateway_selector: Selector { rng: TestRng { rng: ChaCha(ChaCha20Rng { rng: BlockRng { core: ChaChaXCore {}, result_len: 64, index: 64 } }) }, bias_increment: 0 } }, global_dns_records: {Name(aaa.ruwzl.msjhe.): {2001:db80::1}, Name(aaa.feluz.pygfb.): {198.51.100.1}, Name(aaa.rfgc.emlk.ztx.): {198.51.100.1}}, drop_direct_client_traffic: false, network: RoutingTable { routes: {(V4(Ipv4Network { network_address: 203.0.113.1, netmask: 32 }), Client(0)), (V4(Ipv4Network { network_address: 203.0.113.24, netmask: 32 }), Gateway(70703E654B89BF37D9F665)), (V4(Ipv4Network { network_address: 203.0.113.51, netmask: 32 }), Relay(FB6E92EEDC915C5FB99078A9F36D03FA)), (V6(Ipv6Network { network_address: 2001:db80::, netmask: 128 }), Client(0)), (V6(Ipv6Network { network_address: 2001:db80::10, netmask: 128 }), Relay(FB6E92EEDC915C5FB99078A9F36D03FA)), (V6(Ipv6Network { network_address: 2001:db80::35, netmask: 128 }), Gateway(70703E654B89BF37D9F665))} } }, [ActivateResource(Internet(ResourceDescriptionInternet { id: 1FB725D749FE974ECBB1B06514F9EFCF, sites: [Site { id: 68B4BC644DE5F0F249FFB3016558099C, name: "qfvlo" }] })), SendICMPPacketToNonResourceIp { src: 100.64.0.1, dst: 198.51.100.124, seq: 0, identifier: 0 }, SendICMPPacketToNonResourceIp { src: 100.64.0.1, dst: 198.51.100.124, seq: 0, identifier: 0 }], None) cc 1a93e93e7ed05a0e662a464aff213f776aa4e0a471380e0358f90c040163af4e # shrinks to (initial_state, transitions, seen_counter) = (ReferenceState { client: Host { inner: RefClient { id: 0, key: PrivateKey("0000000000000000000000000000000000000000000000000000000000000000"), known_hosts: {}, tunnel_ip4: 100.64.0.1, tunnel_ip6: fd00:2021:1111::, system_dns_resolvers: [0.0.0.0], upstream_dns_resolvers: [], internet_resource: None, connected_internet_resources: false }, ip4: Some(203.0.113.1), ip6: None, default_port: 1, latency: 10ms }, gateways: {0: Host { inner: RefGateway { key: PrivateKey("f52047b91ac11871f9746e01b353884fef6c9ddebe048a7fc0c5bf673e2fb450") }, ip4: Some(203.0.113.30), ip6: Some(2001:db80::39), default_port: 2675, latency: 73ms }}, relays: {4E582D38FE4E528058E3263376518FAB: Host { inner: 9876486316641104771, ip4: Some(203.0.113.28), ip6: Some(2001:db80::1c), default_port: 3478, latency: 30ms }, BF3C922470CE76E068CAEBEBBECBD1EE: Host { inner: 18084935664666890355, ip4: Some(203.0.113.51), ip6: Some(2001:db80::22), default_port: 3478, latency: 17ms }}, partitioned_relays: {}, portal: StubPortal { gateways_by_site: {13DE32EA1F4FD017B7F8DAF66B47438A: {0}}, cidr_resources: {A7CA826336CF675EBB35B297ECFD5F4B: ResourceDescriptionCidr { id: A7CA826336CF675EBB35B297ECFD5F4B, address: V4(Ipv4Network { network_address: 127.0.0.1, netmask: 32 }), name: "xwykj", address_description: Some("uwkynzhaxa"), sites: [Site { id: 13DE32EA1F4FD017B7F8DAF66B47438A, name: "bwkg" }] }}, dns_resources: {D087B227ED9F8ACBD1FF5D13A5EE6CA7: ResourceDescriptionDns { id: D087B227ED9F8ACBD1FF5D13A5EE6CA7, address: "?.vlgnj.llr.yjflr", name: "mgqpbkq", address_description: Some("cyrnd"), sites: [Site { id: 13DE32EA1F4FD017B7F8DAF66B47438A, name: "bwkg" }] }}, internet_resource: ResourceDescriptionInternet { id: 2AFAD7A24A97EF1242FB545A6D5CD4CF, sites: [Site { id: 13DE32EA1F4FD017B7F8DAF66B47438A, name: "bwkg" }] } }, drop_direct_client_traffic: true, global_dns_records: {Name(bzdf.ciqwdl.): {::ffff:11.124.185.251, 63.237.220.221, 127.0.0.1, ::ffff:238.103.250.78}, Name(baz.kcg.): {133.8.59.237, 127.0.0.1, 29.6.44.151, 2635:2c5e:12:cb1c:f0c8:b75c:252a:625, ::ffff:127.0.0.1}, Name(aaa.vlgnj.llr.yjflr.): {198.51.100.230, 198.51.100.238, 198.51.100.10, 198.51.100.231, 198.51.100.215}}, network: RoutingTable { routes: {(V4(Ipv4Network { network_address: 203.0.113.1, netmask: 32 }), Client(0)), (V4(Ipv4Network { network_address: 203.0.113.28, netmask: 32 }), Relay(4E582D38FE4E528058E3263376518FAB)), (V4(Ipv4Network { network_address: 203.0.113.30, netmask: 32 }), Gateway(0)), (V4(Ipv4Network { network_address: 203.0.113.51, netmask: 32 }), Relay(BF3C922470CE76E068CAEBEBBECBD1EE)), (V6(Ipv6Network { network_address: 2001:db80::1c, netmask: 128 }), Relay(4E582D38FE4E528058E3263376518FAB)), (V6(Ipv6Network { network_address: 2001:db80::22, netmask: 128 }), Relay(BF3C922470CE76E068CAEBEBBECBD1EE)), (V6(Ipv6Network { network_address: 2001:db80::39, netmask: 128 }), Gateway(0))} } }, [ActivateResource(Cidr(ResourceDescriptionCidr { id: A7CA826336CF675EBB35B297ECFD5F4B, address: V4(Ipv4Network { network_address: 127.0.0.1, netmask: 32 }), name: "xwykj", address_description: Some("uwkynzhaxa"), sites: [Site { id: 13DE32EA1F4FD017B7F8DAF66B47438A, name: "bwkg" }] })), SendICMPPacketToCidrResource { src: 100.64.0.1, dst: 127.0.0.1, seq: 0, identifier: 0 }, DisconnectRelayFromPortal(4E582D38FE4E528058E3263376518FAB), SendICMPPacketToCidrResource { src: 100.64.0.1, dst: 127.0.0.1, seq: 0, identifier: 0 }], None) cc 8bd553cf41bbf5121bc82aa8524e837407649cda5663db49d25beb4859778e6b # shrinks to (initial_state, transitions, seen_counter) = (ReferenceState { client: Host { inner: RefClient { id: 0, key: PrivateKey("0000000000000000000000000000000000000000000000000000000000000000"), known_hosts: {}, tunnel_ip4: 100.64.0.1, tunnel_ip6: fd00:2021:1111::, system_dns_resolvers: [0.0.0.0], upstream_dns_resolvers: [], internet_resource: None, connected_internet_resources: false }, ip4: Some(203.0.113.1), ip6: None, default_port: 1, latency: 10ms }, gateways: {57EE50D422E: Host { inner: RefGateway { key: PrivateKey("69ce6f875218eb21c7067b2310ac83a747902867de1d02dba79e6724c751b0f8") }, ip4: Some(203.0.113.40), ip6: Some(2001:db80::1e), default_port: 26452, latency: 105ms }}, relays: {BA6E7B175F2D09211C76CEE1444C7A4D: Host { inner: 1116016509051537712, ip4: Some(203.0.113.6), ip6: Some(2001:db80::3f), default_port: 3478, latency: 20ms }}, portal: StubPortal { gateways_by_site: {D0CF44BF77313B7543E0CD400D72213B: {57EE50D422E}}, cidr_resources: {A384479F01B5C02A7C6F5C34ADB6C14F: ResourceDescriptionCidr { id: A384479F01B5C02A7C6F5C34ADB6C14F, address: V6(Ipv6Network { network_address: ::ffff:189.180.186.144, netmask: 124 }), name: "piybibyhqi", address_description: None, sites: [Site { id: D0CF44BF77313B7543E0CD400D72213B, name: "ekgd" }] }, AD57B48BFB398809CCDAE5713C0FB34F: ResourceDescriptionCidr { id: AD57B48BFB398809CCDAE5713C0FB34F, address: V4(Ipv4Network { network_address: 15.179.254.180, netmask: 30 }), name: "aguslztdaa", address_description: None, sites: [Site { id: D0CF44BF77313B7543E0CD400D72213B, name: "ekgd" }] }, 3247CFE7340EB690C88A1E2125348820: ResourceDescriptionCidr { id: 3247CFE7340EB690C88A1E2125348820, address: V6(Ipv6Network { network_address: ::ffff:74.238.61.24, netmask: 127 }), name: "kvggmcw", address_description: Some("mloaep"), sites: [Site { id: D0CF44BF77313B7543E0CD400D72213B, name: "ekgd" }] }}, dns_resources: {25D967F94B981304343D52187D9AB49F: ResourceDescriptionDns { id: 25D967F94B981304343D52187D9AB49F, address: "atv.fonwlo.ygvyqt", name: "tfccbvoper", address_description: None, sites: [Site { id: D0CF44BF77313B7543E0CD400D72213B, name: "ekgd" }] }, 57BB8514BBE1618A89F5548E783F21B2: ResourceDescriptionDns { id: 57BB8514BBE1618A89F5548E783F21B2, address: "*.ovxhn.gymoi.wwfcju", name: "dlrmbbbza", address_description: None, sites: [Site { id: D0CF44BF77313B7543E0CD400D72213B, name: "ekgd" }] }}, internet_resource: ResourceDescriptionInternet { id: 5DD942CAEDB77534D56CD61A8C47A682, sites: [Site { id: D0CF44BF77313B7543E0CD400D72213B, name: "ekgd" }] } }, drop_direct_client_traffic: true, global_dns_records: {Name(aaa.ovxhn.gymoi.wwfcju.): {198.51.100.2}, Name(atv.fonwlo.ygvyqt.): {198.51.100.1}}, network: RoutingTable { routes: {(V4(Ipv4Network { network_address: 203.0.113.1, netmask: 32 }), Client(0)), (V4(Ipv4Network { network_address: 203.0.113.6, netmask: 32 }), Relay(BA6E7B175F2D09211C76CEE1444C7A4D)), (V4(Ipv4Network { network_address: 203.0.113.40, netmask: 32 }), Gateway(57EE50D422E)), (V6(Ipv6Network { network_address: 2001:db80::1e, netmask: 128 }), Gateway(57EE50D422E)), (V6(Ipv6Network { network_address: 2001:db80::3f, netmask: 128 }), Relay(BA6E7B175F2D09211C76CEE1444C7A4D))} } }, [ActivateResource(Cidr(ResourceDescriptionCidr { id: 3247CFE7340EB690C88A1E2125348820, address: V6(Ipv6Network { network_address: ::ffff:74.238.61.24, netmask: 127 }), name: "kvggmcw", address_description: Some("mloaep"), sites: [Site { id: D0CF44BF77313B7543E0CD400D72213B, name: "ekgd" }] })), PartitionRelaysFromPortal, SendICMPPacketToCidrResource { src: fd00:2021:1111::, dst: ::ffff:74.238.61.24, seq: 0, identifier: 0 }, SendICMPPacketToCidrResource { src: fd00:2021:1111::, dst: ::ffff:74.238.61.24, seq: 0, identifier: 0 }], None) +cc cd9badf5b2b92f8adc9e72fa5f464d511117ea56d12e11e7d16f570f88f0ed4d # shrinks to (initial_state, transitions, seen_counter) = (ReferenceState { client: Host { inner: RefClient { id: 0, key: PrivateKey("0000000000000000000000000000000000000000000000000000000000000000"), known_hosts: {}, tunnel_ip4: 100.64.0.1, tunnel_ip6: fd00:2021:1111::, system_dns_resolvers: [0.0.0.0], upstream_dns_resolvers: [IpPort(IpDnsServer { address: 127.0.0.1:53 }), IpPort(IpDnsServer { address: [::ffff:163.255.106.87]:53 })], internet_resource: None, connected_internet_resources: false }, ip4: Some(203.0.113.42), ip6: None, default_port: 64182, latency: 681ms }, gateways: {A94C69EAD1DE2618D76313168E983127: Host { inner: RefGateway { key: PrivateKey("ecd774ea354d3ec3b9e2592364127627d8700dcb844dd089c057c0d9b52c2967") }, ip4: Some(203.0.113.29), ip6: Some(2001:db80::47), default_port: 30474, latency: 64ms }}, relays: {8C87F3CAEF7703500570A8C73382EF4: Host { inner: 12446131234892555706, ip4: Some(203.0.113.92), ip6: Some(2001:db80::31), default_port: 3478, latency: 19ms }, 84EFE2305BF96200D20157FAD9392B81: Host { inner: 1596776720374585331, ip4: Some(203.0.113.95), ip6: Some(2001:db80::56), default_port: 3478, latency: 39ms }}, portal: StubPortal { gateways_by_site: {9B1671AAD2F2568E4E618E0CDB403527: {A94C69EAD1DE2618D76313168E983127}}, cidr_resources: {626974EB6C29E4FC0531BD263843C5B: ResourceDescriptionCidr { id: 626974EB6C29E4FC0531BD263843C5B, address: V4(Ipv4Network { network_address: 127.0.0.0, netmask: 30 }), name: "bshzl", address_description: None, sites: [Site { id: 3847173A5450FDD15672B4DFE30BB103, name: "htuu" }] }, C4CA9F5F1DB1F7BE420C15E308402D53: ResourceDescriptionCidr { id: C4CA9F5F1DB1F7BE420C15E308402D53, address: V4(Ipv4Network { network_address: 37.6.179.224, netmask: 27 }), name: "qruh", address_description: None, sites: [Site { id: 3847173A5450FDD15672B4DFE30BB103, name: "htuu" }] }, 6A39ED528177018C8C17E4E3D8059F35: ResourceDescriptionCidr { id: 6A39ED528177018C8C17E4E3D8059F35, address: V4(Ipv4Network { network_address: 127.0.0.0, netmask: 30 }), name: "rvcloytr", address_description: Some("sxienyg"), sites: [Site { id: 9B1671AAD2F2568E4E618E0CDB403527, name: "brkffqdzaq" }] }, DAFBACED1EC05E40D7912A82FA1FF613: ResourceDescriptionCidr { id: DAFBACED1EC05E40D7912A82FA1FF613, address: V6(Ipv6Network { network_address: 75b5:8a63:fcc:1057:b55f:5c71:adfb:da80, netmask: 121 }), name: "xwftgdy", address_description: Some("qjcyu"), sites: [Site { id: 9B1671AAD2F2568E4E618E0CDB403527, name: "brkffqdzaq" }] }}, dns_resources: {F8AEC835930DA3D8BC7A4AA851E8BE1F: ResourceDescriptionDns { id: F8AEC835930DA3D8BC7A4AA851E8BE1F, address: "?.loqg.jag", name: "ltdvsaxt", address_description: None, sites: [Site { id: 9B1671AAD2F2568E4E618E0CDB403527, name: "brkffqdzaq" }] }}, internet_resource: ResourceDescriptionInternet { id: 50277A4314E568A7271E9AFA411FDEA1, sites: [Site { id: 3847173A5450FDD15672B4DFE30BB103, name: "htuu" }] } }, drop_direct_client_traffic: true, global_dns_records: {Name(qggry.dmh.gwc.): {63e4:d678:a465:7904:4a52:b796:c73e:b46f, bb42:2892:3e9f:b9cf:c7f5:24b9:40c9:9dfb, ::ffff:158.150.200.165}, Name(esx.loqg.jag.): {2001:db80::c7, 2001:db80::4d, 198.51.100.184}, Name(sqjc.offwn.myjeb.): {127.0.0.1, 211.58.134.60, ::ffff:127.0.0.1, ::ffff:248.158.163.234, 18.160.209.164}, Name(vxqmop.yypec.): {::ffff:222.110.46.197, 206.110.36.225, ::ffff:225.208.76.14, ffd0:65dc:76db:9cac:abcc:c363:9f12:ca9, ::ffff:127.0.0.1}, Name(piop.zqh.): {::ffff:127.0.0.1, 168.34.188.130, 59.48.90.6, 127.0.0.1}}, network: RoutingTable { routes: {(V4(Ipv4Network { network_address: 203.0.113.29, netmask: 32 }), Gateway(A94C69EAD1DE2618D76313168E983127)), (V4(Ipv4Network { network_address: 203.0.113.42, netmask: 32 }), Client(0)), (V4(Ipv4Network { network_address: 203.0.113.92, netmask: 32 }), Relay(8C87F3CAEF7703500570A8C73382EF4)), (V4(Ipv4Network { network_address: 203.0.113.95, netmask: 32 }), Relay(84EFE2305BF96200D20157FAD9392B81)), (V6(Ipv6Network { network_address: 2001:db80::31, netmask: 128 }), Relay(8C87F3CAEF7703500570A8C73382EF4)), (V6(Ipv6Network { network_address: 2001:db80::47, netmask: 128 }), Gateway(A94C69EAD1DE2618D76313168E983127)), (V6(Ipv6Network { network_address: 2001:db80::56, netmask: 128 }), Relay(84EFE2305BF96200D20157FAD9392B81))} } }, [ActivateResource(Cidr(ResourceDescriptionCidr { id: 6A39ED528177018C8C17E4E3D8059F35, address: V4(Ipv4Network { network_address: 127.0.0.0, netmask: 30 }), name: "rvcloytr", address_description: Some("sxienyg"), sites: [Site { id: 9B1671AAD2F2568E4E618E0CDB403527, name: "brkffqdzaq" }] })), DisableResources({6A39ED528177018C8C17E4E3D8059F35}), SendDnsQuery { domain: Name(qggry.dmh.gwc.), r_type: A, query_id: 0, dns_server: 127.0.0.1:53 }], None) +cc 107c1b9d283d363f4e6f981d6e72446b90b1f9fdb55ae53816a01f2dfa110d98 # shrinks to (initial_state, transitions, seen_counter) = (ReferenceState { client: Host { inner: RefClient { id: 0, key: PrivateKey("0000000000000000000000000000000000000000000000000000000000000000"), known_hosts: {}, tunnel_ip4: 100.64.0.1, tunnel_ip6: fd00:2021:1111::, system_dns_resolvers: [::ffff:89.50.115.188, 48.21.97.59], upstream_dns_resolvers: [], internet_resource: None, connected_internet_resources: false }, ip4: Some(203.0.113.64), ip6: Some(2001:db80::c), default_port: 28449, latency: 1.029s }, gateways: {3A347E386330C9DAAAA976F1FD8928E0: Host { inner: RefGateway { key: PrivateKey("3afe402418f488d3b99c6cdcc8e61fb997341c47282abeeadc939bf99a476509") }, ip4: Some(203.0.113.25), ip6: Some(2001:db80::1f), default_port: 55041, latency: 109ms }}, relays: {7C3956315A300928A2EEC71420AABD95: Host { inner: 931831688982059303, ip4: Some(203.0.113.55), ip6: Some(2001:db80::2d), default_port: 3478, latency: 15ms }, 955A5580EF8FBBA561E6314DEDE0649D: Host { inner: 8266008346648563466, ip4: Some(203.0.113.71), ip6: Some(2001:db80::57), default_port: 3478, latency: 16ms }}, portal: StubPortal { gateways_by_site: {4C9ADDAF0CDD932DFF927A91B73B6818: {3A347E386330C9DAAAA976F1FD8928E0}}, cidr_resources: {2C1D6B8B949EC368025669E73C947B33: ResourceDescriptionCidr { id: 2C1D6B8B949EC368025669E73C947B33, address: V4(Ipv4Network { network_address: 21.57.236.244, netmask: 32 }), name: "vilu", address_description: Some("jotb"), sites: [Site { id: 4C9ADDAF0CDD932DFF927A91B73B6818, name: "kttribto" }] }}, dns_resources: {D50DA60F6AE2872C0B2CFD01C1722605: ResourceDescriptionDns { id: D50DA60F6AE2872C0B2CFD01C1722605, address: "*.quhif.dlbbuy", name: "nrfdli", address_description: Some("dexnf"), sites: [Site { id: 4C9ADDAF0CDD932DFF927A91B73B6818, name: "kttribto" }] }}, internet_resource: ResourceDescriptionInternet { id: 33AD167A67DFE7BAF024FA4F23D94F93, sites: [Site { id: 4C9ADDAF0CDD932DFF927A91B73B6818, name: "kttribto" }] } }, drop_direct_client_traffic: false, global_dns_records: {Name(jrmt.quhif.dlbbuy.): {2001:db80::92, 2001:db80::ad}}, network: RoutingTable { routes: {(V4(Ipv4Network { network_address: 203.0.113.25, netmask: 32 }), Gateway(3A347E386330C9DAAAA976F1FD8928E0)), (V4(Ipv4Network { network_address: 203.0.113.55, netmask: 32 }), Relay(7C3956315A300928A2EEC71420AABD95)), (V4(Ipv4Network { network_address: 203.0.113.64, netmask: 32 }), Client(0)), (V4(Ipv4Network { network_address: 203.0.113.71, netmask: 32 }), Relay(955A5580EF8FBBA561E6314DEDE0649D)), (V6(Ipv6Network { network_address: 2001:db80::c, netmask: 128 }), Client(0)), (V6(Ipv6Network { network_address: 2001:db80::1f, netmask: 128 }), Gateway(3A347E386330C9DAAAA976F1FD8928E0)), (V6(Ipv6Network { network_address: 2001:db80::2d, netmask: 128 }), Relay(7C3956315A300928A2EEC71420AABD95)), (V6(Ipv6Network { network_address: 2001:db80::57, netmask: 128 }), Relay(955A5580EF8FBBA561E6314DEDE0649D))} } }, [ActivateResource(Dns(ResourceDescriptionDns { id: D50DA60F6AE2872C0B2CFD01C1722605, address: "*.quhif.dlbbuy", name: "nrfdli", address_description: Some("dexnf"), sites: [Site { id: 4C9ADDAF0CDD932DFF927A91B73B6818, name: "kttribto" }] })), DisableResources({2C1D6B8B949EC368025669E73C947B33, D50DA60F6AE2872C0B2CFD01C1722605}), SendDnsQuery { domain: Name(jrmt.quhif.dlbbuy.), r_type: A, query_id: 0, dns_server: [::ffff:89.50.115.188]:53 }, SendICMPPacketToDnsResource { src: 100.64.0.1, dst: Name(jrmt.quhif.dlbbuy.), seq: 0, identifier: 0 }], None) diff --git a/rust/connlib/tunnel/src/client.rs b/rust/connlib/tunnel/src/client.rs index 59a06cbc4..c97e73bf2 100644 --- a/rust/connlib/tunnel/src/client.rs +++ b/rust/connlib/tunnel/src/client.rs @@ -82,6 +82,18 @@ impl ClientTunnel { }); } + pub fn set_disabled_resources(&mut self, new_disabled_resources: HashSet) { + self.role_state + .set_disabled_resource(new_disabled_resources); + + self.role_state + .buffered_events + .push_back(ClientEvent::TunRoutesUpdated { + ip4: self.role_state.routes().filter_map(utils::ipv4).collect(), + ip6: self.role_state.routes().filter_map(utils::ipv6).collect(), + }); + } + pub fn set_tun(&mut self, tun: Box) { self.io.device_mut().set_tun(tun); } @@ -254,7 +266,7 @@ pub struct ClientState { sites_status: HashMap, /// All CIDR resources we know about, indexed by the IP range they cover (like `1.1.0.0/8`). - cidr_resources: IpNetworkTable, + active_cidr_resources: IpNetworkTable, /// All resources indexed by their ID. resources_by_id: HashMap, @@ -276,6 +288,9 @@ pub struct ClientState { /// Configuration of the TUN device, when it is up. interface_config: Option, + /// Resources that have been disabled by the UI + disabled_resources: HashSet, + buffered_events: VecDeque, buffered_packets: VecDeque>, } @@ -296,7 +311,7 @@ impl ClientState { Self { awaiting_connection_details: Default::default(), resources_gateways: Default::default(), - cidr_resources: IpNetworkTable::new(), + active_cidr_resources: IpNetworkTable::new(), resources_by_id: Default::default(), peers: Default::default(), dns_mapping: Default::default(), @@ -310,6 +325,7 @@ impl ClientState { gateways_site: Default::default(), mangled_dns_queries: Default::default(), stub_resolver: StubResolver::new(known_hosts), + disabled_resources: Default::default(), } } @@ -633,7 +649,7 @@ impl ClientState { // In case the DNS server is a CIDR resource, it needs to go through the tunnel. if self.is_upstream_set_by_the_portal() - && self.cidr_resources.longest_match(ip).is_some() + && self.active_cidr_resources.longest_match(ip).is_some() { return Err((packet, ip)); } @@ -769,6 +785,25 @@ impl ClientState { self.mangled_dns_queries.clear(); } + pub fn set_disabled_resource(&mut self, new_disabled_resources: HashSet) { + let current_disabled_resources = self.disabled_resources.clone(); + + // We set disabled_resources before anything else so that add_resource knows what resources are enabled right now. + self.disabled_resources = new_disabled_resources.clone(); + + for re_enabled_resource in current_disabled_resources.difference(&new_disabled_resources) { + let Some(resource) = self.resources_by_id.get(re_enabled_resource) else { + continue; + }; + + self.add_resource(resource.clone()); + } + + for disabled_resource in &new_disabled_resources { + self.disable_resource(*disabled_resource); + } + } + pub fn dns_mapping(&self) -> BiMap { self.dns_mapping.clone() } @@ -781,7 +816,7 @@ impl ClientState { } fn routes(&self) -> impl Iterator + '_ { - self.cidr_resources + self.active_cidr_resources .iter() .map(|(ip, _)| ip) .chain(iter::once(IPV4_RESOURCES.into())) @@ -789,15 +824,22 @@ impl ClientState { .chain(self.dns_mapping.left_values().copied().map(Into::into)) } + fn is_resource_enabled(&self, resource: &ResourceId) -> bool { + !self.disabled_resources.contains(resource) && self.resources_by_id.contains_key(resource) + } + fn get_resource_by_destination(&self, destination: IpAddr) -> Option { let maybe_dns_resource_id = self.stub_resolver.resolve_resource_by_ip(&destination); let maybe_cidr_resource_id = self - .cidr_resources + .active_cidr_resources .longest_match(destination) .map(|(_, res)| res.id); - maybe_dns_resource_id.or(maybe_cidr_resource_id) + // We need to filter disabled resources because we never remove resources from the stub_resolver + maybe_dns_resource_id + .or(maybe_cidr_resource_id) + .filter(|resource| self.is_resource_enabled(resource)) } #[must_use] @@ -955,12 +997,21 @@ impl ClientState { } } + self.resources_by_id + .insert(new_resource.id(), new_resource.clone()); + + if !self.is_resource_enabled(&(new_resource.id())) { + return; + } + match &new_resource { ResourceDescription::Dns(dns) => { self.stub_resolver.add_resource(dns.id, dns.address.clone()); } ResourceDescription::Cidr(cidr) => { - let existing = self.cidr_resources.insert(cidr.address, cidr.clone()); + let existing = self + .active_cidr_resources + .insert(cidr.address, cidr.clone()); match existing { Some(existing) if existing.id != cidr.id => { @@ -974,15 +1025,18 @@ impl ClientState { } ResourceDescription::Internet(_) => {} } - - self.resources_by_id.insert(new_resource.id(), new_resource); } #[tracing::instrument(level = "debug", skip_all, fields(?id))] pub(crate) fn remove_resource(&mut self, id: ResourceId) { + self.disable_resource(id); + self.resources_by_id.remove(&id); + } + + fn disable_resource(&mut self, id: ResourceId) { self.awaiting_connection_details.remove(&id); self.stub_resolver.remove_resource(id); - self.cidr_resources.retain(|_, r| { + self.active_cidr_resources.retain(|_, r| { if r.id == id { tracing::info!(address = %r.address, name = %r.name, "Deactivating CIDR resource"); return false; @@ -991,8 +1045,6 @@ impl ClientState { true }); - self.resources_by_id.remove(&id); - let Some(peer) = peer_by_resource_mut(&self.resources_gateways, &mut self.peers, id) else { return; }; diff --git a/rust/connlib/tunnel/src/dns.rs b/rust/connlib/tunnel/src/dns.rs index 23fed5e1a..04e407be5 100644 --- a/rust/connlib/tunnel/src/dns.rs +++ b/rust/connlib/tunnel/src/dns.rs @@ -190,6 +190,10 @@ impl StubResolver { Some(domain.clone()) } + fn knows_resource(&self, resource: &ResourceId) -> bool { + self.dns_resources.values().contains(resource) + } + // TODO: we can save a few allocations here still // We don't need to support multiple questions/qname in a single query because // nobody does it and since this run with each packet we want to squeeze as much optimization @@ -229,6 +233,13 @@ impl StubResolver { let maybe_resource = self.match_resource(&domain); let resource_records = match (qtype, maybe_resource) { + (_, Some(resource)) if !self.knows_resource(&resource) => { + return Some(ResolveStrategy::ForwardQuery(DnsQuery { + name: domain, + record_type: u16::from(qtype).into(), + query: packet, + })) + } (Rtype::A, Some(resource)) => self.get_or_assign_a_records(domain.clone(), resource), (Rtype::AAAA, Some(resource)) => { self.get_or_assign_aaaa_records(domain.clone(), resource) diff --git a/rust/connlib/tunnel/src/tests/reference.rs b/rust/connlib/tunnel/src/tests/reference.rs index 59858e585..a53c5d83a 100644 --- a/rust/connlib/tunnel/src/tests/reference.rs +++ b/rust/connlib/tunnel/src/tests/reference.rs @@ -172,6 +172,11 @@ impl ReferenceStateMachine for ReferenceState { .with(1, Just(Transition::PartitionRelaysFromPortal)) .with(1, Just(Transition::ReconnectPortal)) .with(1, Just(Transition::Idle)) + .with_if_not_empty(1, state.client.inner().all_resource_ids(), |resources_id| { + sample::subsequence(resources_id.clone(), resources_id.len()).prop_map( + |resources_id| Transition::DisableResources(HashSet::from_iter(resources_id)), + ) + }) .with_if_not_empty( 10, state.client.inner().ipv4_cidr_resource_dsts(), @@ -298,10 +303,16 @@ impl ReferenceStateMachine for ReferenceState { client.cidr_resources.retain(|_, r| &r.id != id); client.dns_resources.remove(id); - client.connected_cidr_resources.remove(id); - client.connected_dns_resources.retain(|(r, _)| r != id); + client.disconnect_resource(id) }); } + Transition::DisableResources(resources) => state.client.exec_mut(|client| { + client.disabled_resources = resources.clone(); + + for id in resources { + client.disconnect_resource(id) + } + }), Transition::SendDnsQuery { domain, r_type, @@ -439,6 +450,7 @@ impl ReferenceStateMachine for ReferenceState { true } + Transition::DisableResources(_) => true, Transition::SendICMPPacketToNonResourceIp { dst, seq, diff --git a/rust/connlib/tunnel/src/tests/sim_client.rs b/rust/connlib/tunnel/src/tests/sim_client.rs index 8efae2e15..eb7011001 100644 --- a/rust/connlib/tunnel/src/tests/sim_client.rs +++ b/rust/connlib/tunnel/src/tests/sim_client.rs @@ -266,6 +266,10 @@ pub struct RefClient { #[derivative(Debug = "ignore")] pub(crate) connected_dns_resources: HashSet<(ResourceId, DomainName)>, + /// Actively disabled resources by the UI + #[derivative(Debug = "ignore")] + pub(crate) disabled_resources: HashSet, + /// The expected ICMP handshakes. /// /// This is indexed by gateway because our assertions rely on the order of the sent packets. @@ -293,6 +297,11 @@ impl RefClient { SimClient::new(self.id, client_state) } + pub(crate) fn disconnect_resource(&mut self, resource: &ResourceId) { + self.connected_cidr_resources.remove(resource); + self.connected_dns_resources.retain(|(r, _)| r != resource); + } + pub(crate) fn reset_connections(&mut self) { self.connected_cidr_resources.clear(); self.connected_dns_resources.clear(); @@ -367,6 +376,10 @@ impl RefClient { }; tracing::Span::current().record("resource", tracing::field::display(rid)); + if self.disabled_resources.contains(&rid) { + return; + } + let Some(gateway) = gateway_by_resource(rid) else { tracing::error!("No gateway for resource"); return; @@ -428,7 +441,9 @@ impl RefClient { ); tracing::debug!("Not connected to resource, expecting to trigger connection intent"); - self.connected_dns_resources.insert((resource, dst)); + if !self.disabled_resources.contains(&resource) { + self.connected_dns_resources.insert((resource, dst)); + } } pub(crate) fn ipv4_cidr_resource_dsts(&self) -> Vec { @@ -460,7 +475,7 @@ impl RefClient { .sorted_by_key(|r| r.address.len()) .rev() .map(|r| r.id) - .next() + .find(|id| !self.disabled_resources.contains(id)) } fn resolved_domains(&self) -> impl Iterator)> + '_ { @@ -541,7 +556,10 @@ impl RefClient { } pub(crate) fn cidr_resource_by_ip(&self, ip: IpAddr) -> Option { - self.cidr_resources.longest_match(ip).map(|(_, r)| r.id) + self.cidr_resources + .longest_match(ip) + .map(|(_, r)| r.id) + .filter(|id| !self.disabled_resources.contains(id)) } pub(crate) fn resolved_ip4_for_non_resources( @@ -736,6 +754,7 @@ fn ref_client( connected_internet_resources: Default::default(), expected_icmp_handshakes: Default::default(), expected_dns_handshakes: Default::default(), + disabled_resources: Default::default(), }, ) } diff --git a/rust/connlib/tunnel/src/tests/sut.rs b/rust/connlib/tunnel/src/tests/sut.rs index 3f6ed1950..37f6917c3 100644 --- a/rust/connlib/tunnel/src/tests/sut.rs +++ b/rust/connlib/tunnel/src/tests/sut.rs @@ -158,6 +158,9 @@ impl StateMachineTest for TunnelTest { Transition::DeactivateResource(id) => { state.client.exec_mut(|c| c.sut.remove_resource(id)) } + Transition::DisableResources(resources) => state + .client + .exec_mut(|c| c.sut.set_disabled_resource(resources)), Transition::SendICMPPacketToNonResourceIp { src, dst, diff --git a/rust/connlib/tunnel/src/tests/transition.rs b/rust/connlib/tunnel/src/tests/transition.rs index b592dc9b0..006c6135a 100644 --- a/rust/connlib/tunnel/src/tests/transition.rs +++ b/rust/connlib/tunnel/src/tests/transition.rs @@ -6,7 +6,7 @@ use connlib_shared::{ use hickory_proto::rr::RecordType; use proptest::{prelude::*, sample}; use std::{ - collections::BTreeMap, + collections::{BTreeMap, HashSet}, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, }; @@ -19,6 +19,8 @@ pub(crate) enum Transition { ActivateResource(ResourceDescription), /// Deactivate a resource on the client. DeactivateResource(ResourceId), + /// Client-side disable resource + DisableResources(HashSet), /// Send an ICMP packet to non-resource IP. SendICMPPacketToNonResourceIp { src: IpAddr,