nat: align probe timing and test receiver IP rejection and endpoint failover
This commit is contained in:
1 parent
38447da5e8
commit
4fab849917
2 files changed
+115
-51
No files matched your search
@@ -4,7 +4,7 @@
|
||||
#include "test_clock.h"
|
||||
|
||||
enum fault_mode { FAULT_NONE, FAULT_NO_PONG, FAULT_FILTERED, FAULT_LATE_PRE, FAULT_CONTACT,
|
||||
FAULT_DEPENDENT, FAULT_UNSTABLE, FAULT_NO_REPORT };
|
||||
FAULT_DEPENDENT, FAULT_UNSTABLE, FAULT_NO_REPORT, FAULT_INGRESS_BLOCKED, FAULT_NO_ANCHOR };
|
||||
|
||||
static struct {
|
||||
struct nat_fixture *fixture;
|
||||
@@ -57,7 +57,7 @@ ssize_t __wrap_socket_sendto(socket_t fd, const void *packet, size_t length, con
|
||||
struct sockaddr_storage destination = {0}; assert(target_length <= sizeof(destination));
|
||||
memcpy(&destination, target, target_length);
|
||||
int to_owner = route_ping_addr_equal(&destination, &fault.socket->local_addr, 1);
|
||||
if (fault.mode == FAULT_NO_PONG && to_owner && plain[3] == ETCP_PONG) {
|
||||
if ((fault.mode == FAULT_NO_PONG || fault.mode == FAULT_NO_ANCHOR) && to_owner && plain[3] == ETCP_PONG) {
|
||||
fault.dropped++; return length;
|
||||
}
|
||||
if (source == fault.socket && plain[3] == ETCP_PING && (plain[4] & ETCP_PING_FLAG_OBSERVE) &&
|
||||
@@ -79,7 +79,8 @@ ssize_t __wrap_socket_sendto(socket_t fd, const void *packet, size_t length, con
|
||||
&source->local_addr, 500, ignored_ping, NULL, NULL, 0, 0));
|
||||
DEBUG_INFO(DEBUG_CATEGORY_NAT, "fault fixture: real outgoing PING contaminates PRE source IP");
|
||||
}
|
||||
if ((fault.mode == FAULT_FILTERED || fault.mode == FAULT_LATE_PRE) && !fault.contacted) {
|
||||
if (fault.mode == FAULT_INGRESS_BLOCKED ||
|
||||
((fault.mode == FAULT_FILTERED || fault.mode == FAULT_LATE_PRE || fault.mode == FAULT_NO_ANCHOR) && !fault.contacted)) {
|
||||
if (fault.mode == FAULT_LATE_PRE && !fault.delayed_length && !fault.injected) {
|
||||
memcpy(fault.delayed, packet, length); fault.delayed_length = length; fault.delayed_fd = fd;
|
||||
fault.delayed_target = destination; fault.delayed_target_length = target_length;
|
||||
@@ -138,6 +139,57 @@ static void run_case(enum fault_mode mode, uint8_t mapping, uint8_t inbound) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_NAT, "PASS NAT fault mode=%d", mode);
|
||||
}
|
||||
|
||||
/* Разные ключи не означают разные IP: неподходящего помощника отклоняет получатель. */
|
||||
static void run_alias(const char *alias_ip) {
|
||||
struct nat_fixture fixture; nat_fixture_init(&fixture);
|
||||
struct SC_MYKEYS first, second; assert(sc_generate_keypair(&first) == SC_OK && sc_generate_keypair(&second) == SC_OK);
|
||||
if (sc_derive_node_id_from_pubkey(first.public_key) > sc_derive_node_id_from_pubkey(second.public_key)) {
|
||||
struct SC_MYKEYS swap = first; first = second; second = swap;
|
||||
}
|
||||
struct UTUN_INSTANCE *owner = nat_fixture_node(&fixture, "127.0.0.2", NULL, NULL);
|
||||
struct UTUN_INSTANCE *observer = nat_fixture_node(&fixture, "127.0.0.3", NULL, NULL);
|
||||
struct UTUN_INSTANCE *alias = nat_fixture_node(&fixture, alias_ip, &first, NULL);
|
||||
struct UTUN_INSTANCE *helper = nat_fixture_node(&fixture, "127.0.0.4", &second, NULL);
|
||||
nat_detection_set_automatic(observer->nat_det, 0); nat_detection_set_automatic(alias->nat_det, 0);
|
||||
nat_detection_set_automatic(helper->nat_det, 0);
|
||||
nat_fixture_connect(&fixture, observer, "udp", alias); nat_fixture_connect(&fixture, observer, "udp", helper);
|
||||
nat_fixture_connect(&fixture, owner, "udp", observer); nat_detection_set_automatic(owner->nat_det, 0);
|
||||
struct ETCP_SOCKET *socket = test_etcp_bound_socket(owner, "udp");
|
||||
assert(!nat_detection_request_check_socket(owner->nat_det, socket, observer->node_id));
|
||||
struct nat_check_status status = {0}; uint64_t end = get_time_tb() + 400000;
|
||||
do { test_clock_poll(fixture.ua, 1000); assert(!nat_detection_get_status(owner->nat_det, socket, &status)); }
|
||||
while (get_time_tb() < end && (!status.rounds || status.phase || status.cycling));
|
||||
assert(socket->address_profile.mapping == ADDRESS_MAP_UNCHANGED && socket->address_profile.inbound == ADDRESS_IN_OPEN);
|
||||
assert(status.helper == helper->node_id && status.helper_reselections);
|
||||
nat_fixture_cleanup(&fixture);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_NAT, "PASS NAT receiver rejects helper source=%s", alias_ip);
|
||||
}
|
||||
|
||||
/* У наблюдателя первый UDP listener недоступен, но управление по TCP и второй IP работают. */
|
||||
static void run_endpoint_retry(void) {
|
||||
struct nat_fixture fixture; nat_fixture_init(&fixture);
|
||||
struct UTUN_INSTANCE *owner = nat_fixture_node(&fixture, "127.0.0.2", NULL,
|
||||
"[server:tcp]\naddr=127.0.0.2:0\ntransport=tcp\ntype=public\n");
|
||||
struct UTUN_INSTANCE *observer = nat_fixture_node(&fixture, "127.0.0.3", NULL,
|
||||
"[server:other]\naddr=127.0.0.8:0\ntype=public\n[server:tcp]\naddr=127.0.0.3:0\ntransport=tcp\ntype=public\n");
|
||||
struct UTUN_INSTANCE *helper = nat_fixture_node(&fixture, "127.0.0.4", NULL,
|
||||
"[server:tcp]\naddr=127.0.0.4:0\ntransport=tcp\ntype=public\n");
|
||||
nat_detection_set_automatic(observer->nat_det, 0); nat_detection_set_automatic(helper->nat_det, 0);
|
||||
struct ETCP_SOCKET *bad = test_etcp_bound_socket(observer, "udp");
|
||||
assert(!uasync_remove_socket_t(fixture.ua, bad->fd)); bad->socket_id = NULL;
|
||||
nat_fixture_connect(&fixture, observer, "tcp", helper); nat_fixture_connect(&fixture, owner, "tcp", observer);
|
||||
nat_detection_set_automatic(owner->nat_det, 0);
|
||||
struct ETCP_SOCKET *socket = test_etcp_bound_socket(owner, "udp");
|
||||
assert(!nat_detection_request_check_socket(owner->nat_det, socket, observer->node_id));
|
||||
struct nat_check_status status = {0}; uint64_t end = get_time_tb() + 400000;
|
||||
do { test_clock_poll(fixture.ua, 1000); assert(!nat_detection_get_status(owner->nat_det, socket, &status)); }
|
||||
while (get_time_tb() < end && (!status.rounds || status.phase || status.cycling));
|
||||
assert(socket->address_profile.mapping == ADDRESS_MAP_UNCHANGED && socket->address_profile.inbound == ADDRESS_IN_OPEN);
|
||||
assert(status.helper_reselections && status.observer == observer->node_id);
|
||||
nat_fixture_cleanup(&fixture);
|
||||
DEBUG_INFO(DEBUG_CATEGORY_NAT, "PASS NAT retries another observer IP after timeout");
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN); debug_set_category_level(DEBUG_CATEGORY_NAT, DEBUG_LEVEL_DEBUG);
|
||||
test_clock_init(1000);
|
||||
@@ -148,5 +200,8 @@ int main(void) {
|
||||
run_case(FAULT_DEPENDENT, ADDRESS_MAP_DEPENDENT, ADDRESS_IN_OPEN);
|
||||
run_case(FAULT_UNSTABLE, ADDRESS_MAP_UNKNOWN, ADDRESS_IN_UNKNOWN);
|
||||
run_case(FAULT_NO_REPORT, ADDRESS_MAP_UNKNOWN, ADDRESS_IN_UNKNOWN);
|
||||
run_case(FAULT_INGRESS_BLOCKED, ADDRESS_MAP_UNCHANGED, ADDRESS_IN_UNKNOWN);
|
||||
run_case(FAULT_NO_ANCHOR, ADDRESS_MAP_UNCHANGED, ADDRESS_IN_UNKNOWN);
|
||||
run_alias("127.0.0.3"); run_alias("127.0.0.2"); run_endpoint_retry();
|
||||
test_clock_finish(); return 0;
|
||||
}
|
||||
Reference in new issue
Block a user