comparison quic_migration.t @ 1893:6dcf5a1df790

Tests: basic QUIC connection migration tests.
author Sergey Kandaurov <pluknet@nginx.com>
date Tue, 23 May 2023 18:55:06 +0400
parents
children 8b74936ff2ac
comparison
equal deleted inserted replaced
1892:a8fc2f1f6f6f 1893:6dcf5a1df790
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 ###############################################################################