Skip to content

Commit 1b7164a

Browse files
committed
Tests: basic QUIC connection migration tests.
1 parent b6b8f75 commit 1b7164a

File tree

1 file changed

+139
-0
lines changed

1 file changed

+139
-0
lines changed

quic_migration.t

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
#!/usr/bin/perl
2+
3+
# (C) Sergey Kandaurov
4+
# (C) Nginx, Inc.
5+
6+
# Tests for quic connection migration.
7+
8+
###############################################################################
9+
10+
use warnings;
11+
use strict;
12+
13+
use Test::More;
14+
15+
BEGIN { use FindBin; chdir($FindBin::Bin); }
16+
17+
use lib 'lib';
18+
use Test::Nginx;
19+
use Test::Nginx::HTTP3;
20+
21+
###############################################################################
22+
23+
select STDERR; $| = 1;
24+
select STDOUT; $| = 1;
25+
26+
eval { require Crypt::Misc; die if $Crypt::Misc::VERSION < 0.067; };
27+
plan(skip_all => 'CryptX version >= 0.067 required') if $@;
28+
29+
plan(skip_all => '127.0.0.20 local address required')
30+
unless defined IO::Socket::INET->new( LocalAddr => '127.0.0.20' );
31+
32+
my $t = Test::Nginx->new()->has(qw/http http_v3/)
33+
->has_daemon('openssl')->plan(2);
34+
35+
$t->write_file_expand('nginx.conf', <<'EOF');
36+
37+
%%TEST_GLOBALS%%
38+
39+
daemon off;
40+
41+
events {
42+
}
43+
44+
http {
45+
%%TEST_GLOBALS_HTTP%%
46+
47+
ssl_certificate_key localhost.key;
48+
ssl_certificate localhost.crt;
49+
50+
server {
51+
listen 127.0.0.1:%%PORT_8980_UDP%% quic;
52+
server_name localhost;
53+
54+
location / {
55+
add_header X-IP $remote_addr;
56+
}
57+
}
58+
}
59+
60+
EOF
61+
62+
$t->write_file('openssl.conf', <<EOF);
63+
[ req ]
64+
default_bits = 2048
65+
encrypt_key = no
66+
distinguished_name = req_distinguished_name
67+
[ req_distinguished_name ]
68+
EOF
69+
70+
my $d = $t->testdir();
71+
72+
foreach my $name ('localhost') {
73+
system('openssl req -x509 -new '
74+
. "-config $d/openssl.conf -subj /CN=$name/ "
75+
. "-out $d/$name.crt -keyout $d/$name.key "
76+
. ">>$d/openssl.out 2>&1") == 0
77+
or die "Can't create certificate for $name: $!\n";
78+
}
79+
80+
$t->write_file('index.html', '');
81+
$t->run();
82+
83+
###############################################################################
84+
85+
# test that $remote_addr is not truncated after migration (ticket #2488),
86+
# to test, we migrate to another address large enough in text representation,
87+
# then send a request on the new path
88+
89+
my $s = Test::Nginx::HTTP3->new();
90+
$s->new_connection_id(1, 0, "connection_id_1", "reset_token_0001");
91+
92+
my $frames = $s->read(all => [{ type => 'NCID' }]);
93+
my ($frame) = grep { $_->{type} eq "NCID" } @$frames;
94+
95+
$s->{socket} = IO::Socket::INET->new(
96+
Proto => "udp",
97+
LocalAddr => '127.0.0.20',
98+
PeerAddr => '127.0.0.1:' . port(8980),
99+
);
100+
$s->{scid} = "connection_id_1";
101+
$s->{dcid} = $frame->{cid};
102+
$s->ping();
103+
104+
$frames = $s->read(all => [{ type => 'PATH_CHALLENGE' }]);
105+
($frame) = grep { $_->{type} eq "PATH_CHALLENGE" } @$frames;
106+
$s->path_response($frame->{data});
107+
108+
$frames = $s->read(all => [{ sid => $s->new_stream(), fin => 1 }]);
109+
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
110+
is($frame->{headers}{'x-ip'}, '127.0.0.20', 'remote addr after migration');
111+
112+
# test that $remote_addr is not truncated while in the process of migration;
113+
# the same but migration occurs on receiving a request stream itself,
114+
# which is the first non-probing frame on the new path;
115+
# this might lead to $remote_addr truncation in the following order:
116+
# - stream held original sockaddr/addr_text references on stream creation
117+
# - values were rewritten as part of handling connection migration
118+
# - stream was handled referencing rewritten values, with old local lengths
119+
# sockaddr and addr_text are expected to keep copies on stream creation
120+
121+
$s = Test::Nginx::HTTP3->new();
122+
$s->new_connection_id(1, 0, "connection_id_1", "reset_token_0001");
123+
124+
$frames = $s->read(all => [{ type => 'NCID' }]);
125+
($frame) = grep { $_->{type} eq "NCID" } @$frames;
126+
127+
$s->{socket} = IO::Socket::INET->new(
128+
Proto => "udp",
129+
LocalAddr => '127.0.0.20',
130+
PeerAddr => '127.0.0.1:' . port(8980),
131+
);
132+
$s->{scid} = "connection_id_1";
133+
$s->{dcid} = $frame->{cid};
134+
135+
$frames = $s->read(all => [{ sid => $s->new_stream(), fin => 1 }]);
136+
($frame) = grep { $_->{type} eq "HEADERS" } @$frames;
137+
is($frame->{headers}{'x-ip'}, '127.0.0.1', 'remote addr on migration');
138+
139+
###############################################################################

0 commit comments

Comments
 (0)