1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
|
id = 2433
title = "[TestCase] -object filter-redirector completely ignores linked bidirectional chardev, so encryption for netdev is broken"
state = "opened"
created_at = "2024-07-11T16:11:51.641Z"
closed_at = "n/a"
labels = ["Chardev", "Networking"]
url = "https://gitlab.com/qemu-project/qemu/-/issues/2433"
host-os = "Windows 11 23H2 Home"
host-arch = "x86_64"
qemu-version = "v9.0.0-12054-g923cf646f4"
guest-os = "n/a"
guest-arch = "x86"
description = """If I form a wittingly broken network topology using -object filter-redirector and an encrypting bi-directional chardev linked to redirected traffic, the topology continues to function when it must not. See Fig.2.
By "continues to function", I mean the two guest Windows XP from Fig.2 topology are able to see each other, join the same "MSHOME" workgroup, make shared folders which are mutually seen from each other and even send files to each other's shared folder!
\\
Why do I consider Fig.2 a broken topology? It includes only one encrypting chardev, whereas a normal encrypted network topology must contain one encrypting and one decrypting chardev.\\
To form Fig.2 topology, follow "Steps to reproduce" section.\\
\\
At the same time, -object filter-redirector works perfectly if only uni-directional chardevs are used, see Fig.1 with corresponding commands to launch guest#1 qemu and guest#2 qemu. All network activities from previous paragraphs seem to function correctly both in Fig.1 and in Fig.2
If I put tls-creds=tls0, inside any "-chardev socket" switch in Fig.1 to make traffic encrypted without further decryption, local network between guests becomes broken (0 packets received), which is normal and expected behaviour.\\
\\
The end goal is to have netdev traffic encrypted. If anyone knows a workaround to encrypt netdev traffic on Windows hosts without installing crypto libs/drivers besides GnuTLS, please describe it in comments.
*** Please note that some old broswers show Fig.1 and Fig.2 a little bit screwed. If so, please copy their source to Mousepad or Notepad - they must show topology correctly. And disable "Word Wrap" mode in your text editor, of course. ***
```
*********************** Fig. 1. Perfectly working network topology with uni-directional chardevs *************************
NOTE: rx:receive packets sent to the netdev
tx:receive packets sent by the netdev
First qemu Second qemu
+--------------------------------------------------------------------------------------------------+ +----------------------------------------+
| | | |
| +----------------------------------------------------------------------------------------+ | | +------------------------------+ |
| | Guest Windows XP #1: | | | | Guest Windows XP #2: | |
| | | | | | | |
| | 169.254.144.98 IP, | | | | 169.254.144.99 IP, | |
| | 255.255.0.0 Net mask, | | | | 255.255.0.0 Net mask, | |
| | Gateway empty, | | | | Gateway empty, | |
| | DNS server empty, | | | | DNS server empty, | |
| | WINS server empty, | | | | WINS server empty, | |
| | DHCP off | | | | DHCP off | |
| +----------------------------------------------------------------------------------------+ | | +------------------------------+ |
| ^ | | | ^ | |
| | all | | | | | |
| | V | | | | |
| +--------------+ | | | | |
| | | | | | | |
| indev | filter | outdev | | | | |
| +-----> redirector >-------+ | | | | |
| | | | | | | | | |
| | | queue=all | | | | | | |
| | +--------------+ | | | | | |
| | | | | | | |
| +------------+ +------------+ | | | | |
| | | | | | | |
| +------------------+ +------------------+ | | +-------------------+ +------------------+ | | | | |
| | :9001 | | :9001 | | | | :9002 | | :9002 | | | | | |
| | uni-directional | | uni-directional | | | | uni-directional | | uni-directional | | | | all | |
| +-> chardev |->| chardev >-+ +-> chardev |->| chardev >-+ | | | | |
| | | | | | | | | | | | | | | |
| | | id=tx_in | |id=tx_out_to_guest| |id=rx_in_from_guest| | id=rx_out | | | | | | |
| | | server=on | | | | | | server=on | | | | | | |
| | +------------------+ +------------------+ +-------------------+ +------------------+ | | | | | |
| | | | | | | |
| | | | | | | |
| | +----------------+ +----------------+ | | | | | |
| | | | | | | | | | | |
| | | filter | | filter | | | | | | |
| +-----------------------< redirector | | redirector <------------------------+ | | | | |
| outdev | | | | indev | | | | |
| | queue=tx | | queue=rx | | | | | |
| +--------+-------+ +--------+-------+ | | | | |
| | | | | | | |
| | | | | | V |
| +--------------------------------^---------------------------V-----------------------------+ | | +--------------------------------+ |
| |==========================================================================================|------------->|================================| |
| | | | | | | | | |
| | netdev | mac=52:54:00:12:34:56 |7001:: ::7001| netdev | mac=52:54:00:12:34:57 | |
| | | | | | | | | |
| | | |<-------------| | | |
| +------------------------------------------------------------------------------------------+ | | +--------------------------------+ |
| | | |
+--------------------------------------------------------------------------------------------------+ +----------------------------------------+
Command to run Guest Windows XP #1 from Fig.1:
qemu-system-i386.exe \\
-accel tcg \\
-m 256M \\
-cpu Westmere \\
-hda d:\\xp1.qcow2 \\
-usb -device usb-tablet \\
-netdev socket,id=net0,listen=localhost:7001 \\
-device rtl8139,netdev=net0,mac=52:54:00:12:34:56 \\
-chardev socket,id=tx_in,host=127.0.0.1,port=9001,server=on,wait=off \\
-chardev socket,id=tx_out_to_guest,host=127.0.0.1,port=9001 \\
-chardev socket,id=rx_out,host=127.0.0.1,port=9002,server=on,wait=off \\
-chardev socket,id=rx_in_from_guest,host=127.0.0.1,port=9002 \\
-object filter-redirector,netdev=net0,queue=tx,outdev=tx_in,id=tx1 \\
-object filter-redirector,netdev=net0,queue=rx,indev=rx_out,id=rx1 \\
-object filter-redirector,netdev=net0,queue=all,outdev=rx_in_from_guest,indev=tx_out_to_guest,id=inner_redirector
Command to run Guest Windows XP #2 from Fig.1:
qemu-system-i386.exe
-accel tcg \\
-m 256M \\
-cpu Westmere \\
-hda d:\\xp2.qcow2 \\
-usb -device usb-tablet \\
-netdev socket,id=net1,connect=localhost:7001 \\
-device rtl8139,netdev=net1,mac=52:54:00:12:34:57
*********************** Fig. 2. Erroneously working network topology, despite encrypting bi-directional chardev *************************
NOTE: queue=rx:receive packets sent to the netdev
queue=tx:receive packets sent by the netdev
queue=all:receive packets sent by and to the netdev (both directions)
First qemu Second qemu
+--------------------------------------------------------------------------------------------------+ +----------------------------------------+
| | | |
| +----------------------------------------------------------------------------------------+ | | +------------------------------+ |
| | Guest Windows XP #1: | | | | Guest Windows XP #2: | |
| | | | | | | |
| | 169.254.144.98 IP, | | | | 169.254.144.99 IP, | |
| | 255.255.0.0 Net mask, | | | | 255.255.0.0 Net mask, | |
| | Gateway empty, | | | | Gateway empty, | |
| | DNS server empty, | | | | DNS server empty, | |
| | WINS server empty, | | | | WINS server empty, | |
| | DHCP off | | | | DHCP off | |
| +----------------------------------------------------------------------------------------+ | | +------------------------------+ |
| ^ | | | ^ | |
| | all | | | | | |
| | V | | | | |
| +-------------------+ | | | | |
| | | | | | | |
| +------>| filter | | | | | |
| | | redirector | | | | | |
| | +--<| | | | | | |
| | | | queue=all | | | | | |
| | | |id=inner_redirector| | | | | |
| | | +-----------V-------+ | | | | |
| | | | indev | | | | |
| | | | | | | | |
| | | | | | | | |
| | | +----------V-------+ +-----------------------+ | | | | |
| | | | :9001 | | | | | | | |
| | | | bi-directional | | -object tls-creds-psk | | | | | |
| | | |encrypting chardev| | | | | | | |
| | | | |---->| | | | | | |
| | | | tls-creds=tls0 | | id=tls0 | | | | | |
| | | | id=inner_chardev | | endpoint=server | | | | | |
| | | | server=on | | | | | | | |
| | | +------------------+ +-----------------------+ | | | | |
| | | | | | | |
| | | | | | | |
| ^ V | | | V |
| +------------------------------------------------------------------------------------------+ | | +--------------------------------+ |
| |==========================================================================================|------------->|================================| |
| | | | | | | | | |
| | netdev | mac=52:54:00:12:34:56 |7001:: ::7001| netdev | mac=52:54:00:12:34:57 | |
| | | | | | | | | |
| | | |<-------------| | | |
| +------------------------------------------------------------------------------------------+ | | +--------------------------------+ |
| | | |
+--------------------------------------------------------------------------------------------------+ +----------------------------------------+
```"""
reproduce = """1. Download official GnuTLS .zip for windows from https://www.gnutls.org/download.html and extract it.
2. Download and install official QEMU 9.0 from https://qemu.weilnetz.de/w64/qemu-w64-setup-20240423.exe
3. Open command prompt, navigate to the folder with psktool.exe from Step 1.
4. Run this command: "psktool -u qemu_user -p keys.psk"
5. Run first guest Windows XP with the command described in "QEMU command line" section above, replacing "dir=C:\\\\Downloads" with path to keys.psk, like this: "dir=C:\\\\path_to_keys_dot_psk" (without filename itself)
6. Run second guest Windows XP with the following command: `qemu-system-i386.exe -accel tcg -m 256M -cpu Westmere -hda d:\\\\xp2.qcow2 -usb -device usb-tablet -netdev socket,id=net1,connect=localhost:7001 -device rtl8139,netdev=net1,mac=52:54:00:12:34:57`"""
additional = """Yes, I know Qemu on Linux hosts is able to encrypt netdev traffic with the aid of `-netdev vhost-user,id=net0,chardev=chr0`\\
But `-netdev vhost-user,id=net0,chardev=chr0` is not officially supported by Qemu on Windows hosts.\\
\\
If I run this command in one command prompt instance:\\
`qemu-system-i386.exe -accel tcg -m 256M -object tls-creds-psk,id=tls0,endpoint=server,dir=C:\\Downloads -chardev socket,id=chr0,port=7001,host=127.0.0.1,tls-creds=tls0,server=on -netdev vhost-user,id=net0,chardev=chr0 -device virtio-net-pci,netdev=net0,mac=52:54:00:12:34:56`\\
\\
And this one in another instance\\
`gnutls-cli.exe --priority=NORMAL -p 7001 --pskusername=pskusername_from_keys_psk_file --pskkey=pskkeyhash_from_keys_psk_file 127.0.0.1`\\
\\
I see this:\\
`qemu-system-i386.exe: -netdev vhost-user,id=net0,chardev=chr0: network backend 'vhost-user' is not compiled into this binary`\\
\\
Testcase:
<details>
static void test_redirector_incomplete_bidirectional_topology_connectionError(void)\\
{\\
//prepare keys.psk\\
FILE \\*fileAddress;\\
fileAddress = fopen("/home/keys.psk", "w");\\
char content\\[50\\] = "deadbeefname:deadbeefkey";\\
int i;\\
int len = strlen(content);\\
\\
if (fileAddress != NULL) {\\
for (i = 0; i \\< len; i++) {\\
fputc (content\\[i\\], fileAddress);\\
}\\
fclose(fileAddress); \\
}\\
else {\\
return -1;\\
}\\
\\
\\
QTestState \\*qts0;\\
char \\*expect;\\
\\
qts0 = qtest_initf("-netdev socket,id=net0,listen=localhost:7001 "\\
"-device rtl8139,netdev=net0,mac=52:54:00:12:34:56 "\\
"-object filter-redirector,netdev=net0,queue=all,indev=inner_chardev,id=inner_redirector"\\
"-chardev socket,id=inner_chardev,host=127.0.0.1,port=9001,tls-creds=tls0,server=on,wait=off"\\
"-object tls-creds-psk,id=tls0,endpoint=server,dir=/home/");\\
\\
expect = g_strdup_printf("st0: index=0,type=socket,connection error\\\\r\\\\n");\\
\\
EXPECT_STATE(qts0, expect, 0);\\
\\
g_free(expect);\\
\\
qtest_quit(qts0);\\
}
</details>"""
|