-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathNetworkNamespace.DE.html
684 lines (613 loc) · 34 KB
/
NetworkNamespace.DE.html
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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<!-- 2024-02-29 Do 11:18 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Virtuelles Netzwerk mit Open vSwitch</title>
<meta name="author" content="Sebastian Meisel" />
<meta name="generator" content="Org Mode" />
<style>
#content { max-width: 60em; margin: auto; }
.title { text-align: center;
margin-bottom: .2em; }
.subtitle { text-align: center;
font-size: medium;
font-weight: bold;
margin-top:0; }
.todo { font-family: monospace; color: red; }
.done { font-family: monospace; color: green; }
.priority { font-family: monospace; color: orange; }
.tag { background-color: #eee; font-family: monospace;
padding: 2px; font-size: 80%; font-weight: normal; }
.timestamp { color: #bebebe; }
.timestamp-kwd { color: #5f9ea0; }
.org-right { margin-left: auto; margin-right: 0px; text-align: right; }
.org-left { margin-left: 0px; margin-right: auto; text-align: left; }
.org-center { margin-left: auto; margin-right: auto; text-align: center; }
.underline { text-decoration: underline; }
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
p.verse { margin-left: 3%; }
pre {
border: 1px solid #e6e6e6;
border-radius: 3px;
background-color: #f2f2f2;
padding: 8pt;
font-family: monospace;
overflow: auto;
margin: 1.2em;
}
pre.src {
position: relative;
overflow: auto;
}
pre.src:before {
display: none;
position: absolute;
top: -8px;
right: 12px;
padding: 3px;
color: #555;
background-color: #f2f2f299;
}
pre.src:hover:before { display: inline; margin-top: 14px;}
/* Languages per Org manual */
pre.src-asymptote:before { content: 'Asymptote'; }
pre.src-awk:before { content: 'Awk'; }
pre.src-authinfo::before { content: 'Authinfo'; }
pre.src-C:before { content: 'C'; }
/* pre.src-C++ doesn't work in CSS */
pre.src-clojure:before { content: 'Clojure'; }
pre.src-css:before { content: 'CSS'; }
pre.src-D:before { content: 'D'; }
pre.src-ditaa:before { content: 'ditaa'; }
pre.src-dot:before { content: 'Graphviz'; }
pre.src-calc:before { content: 'Emacs Calc'; }
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
pre.src-fortran:before { content: 'Fortran'; }
pre.src-gnuplot:before { content: 'gnuplot'; }
pre.src-haskell:before { content: 'Haskell'; }
pre.src-hledger:before { content: 'hledger'; }
pre.src-java:before { content: 'Java'; }
pre.src-js:before { content: 'Javascript'; }
pre.src-latex:before { content: 'LaTeX'; }
pre.src-ledger:before { content: 'Ledger'; }
pre.src-lisp:before { content: 'Lisp'; }
pre.src-lilypond:before { content: 'Lilypond'; }
pre.src-lua:before { content: 'Lua'; }
pre.src-matlab:before { content: 'MATLAB'; }
pre.src-mscgen:before { content: 'Mscgen'; }
pre.src-ocaml:before { content: 'Objective Caml'; }
pre.src-octave:before { content: 'Octave'; }
pre.src-org:before { content: 'Org mode'; }
pre.src-oz:before { content: 'OZ'; }
pre.src-plantuml:before { content: 'Plantuml'; }
pre.src-processing:before { content: 'Processing.js'; }
pre.src-python:before { content: 'Python'; }
pre.src-R:before { content: 'R'; }
pre.src-ruby:before { content: 'Ruby'; }
pre.src-sass:before { content: 'Sass'; }
pre.src-scheme:before { content: 'Scheme'; }
pre.src-screen:before { content: 'Gnu Screen'; }
pre.src-sed:before { content: 'Sed'; }
pre.src-sh:before { content: 'shell'; }
pre.src-sql:before { content: 'SQL'; }
pre.src-sqlite:before { content: 'SQLite'; }
/* additional languages in org.el's org-babel-load-languages alist */
pre.src-forth:before { content: 'Forth'; }
pre.src-io:before { content: 'IO'; }
pre.src-J:before { content: 'J'; }
pre.src-makefile:before { content: 'Makefile'; }
pre.src-maxima:before { content: 'Maxima'; }
pre.src-perl:before { content: 'Perl'; }
pre.src-picolisp:before { content: 'Pico Lisp'; }
pre.src-scala:before { content: 'Scala'; }
pre.src-shell:before { content: 'Shell Script'; }
pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
/* additional language identifiers per "defun org-babel-execute"
in ob-*.el */
pre.src-cpp:before { content: 'C++'; }
pre.src-abc:before { content: 'ABC'; }
pre.src-coq:before { content: 'Coq'; }
pre.src-groovy:before { content: 'Groovy'; }
/* additional language identifiers from org-babel-shell-names in
ob-shell.el: ob-shell is the only babel language using a lambda to put
the execution function name together. */
pre.src-bash:before { content: 'bash'; }
pre.src-csh:before { content: 'csh'; }
pre.src-ash:before { content: 'ash'; }
pre.src-dash:before { content: 'dash'; }
pre.src-ksh:before { content: 'ksh'; }
pre.src-mksh:before { content: 'mksh'; }
pre.src-posh:before { content: 'posh'; }
/* Additional Emacs modes also supported by the LaTeX listings package */
pre.src-ada:before { content: 'Ada'; }
pre.src-asm:before { content: 'Assembler'; }
pre.src-caml:before { content: 'Caml'; }
pre.src-delphi:before { content: 'Delphi'; }
pre.src-html:before { content: 'HTML'; }
pre.src-idl:before { content: 'IDL'; }
pre.src-mercury:before { content: 'Mercury'; }
pre.src-metapost:before { content: 'MetaPost'; }
pre.src-modula-2:before { content: 'Modula-2'; }
pre.src-pascal:before { content: 'Pascal'; }
pre.src-ps:before { content: 'PostScript'; }
pre.src-prolog:before { content: 'Prolog'; }
pre.src-simula:before { content: 'Simula'; }
pre.src-tcl:before { content: 'tcl'; }
pre.src-tex:before { content: 'TeX'; }
pre.src-plain-tex:before { content: 'Plain TeX'; }
pre.src-verilog:before { content: 'Verilog'; }
pre.src-vhdl:before { content: 'VHDL'; }
pre.src-xml:before { content: 'XML'; }
pre.src-nxml:before { content: 'XML'; }
/* add a generic configuration mode; LaTeX export needs an additional
(add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
pre.src-conf:before { content: 'Configuration File'; }
table { border-collapse:collapse; }
caption.t-above { caption-side: top; }
caption.t-bottom { caption-side: bottom; }
td, th { vertical-align:top; }
th.org-right { text-align: center; }
th.org-left { text-align: center; }
th.org-center { text-align: center; }
td.org-right { text-align: right; }
td.org-left { text-align: left; }
td.org-center { text-align: center; }
dt { font-weight: bold; }
.footpara { display: inline; }
.footdef { margin-bottom: 1em; }
.figure { padding: 1em; }
.figure p { text-align: center; }
.equation-container {
display: table;
text-align: center;
width: 100%;
}
.equation {
vertical-align: middle;
}
.equation-label {
display: table-cell;
text-align: right;
vertical-align: middle;
}
.inlinetask {
padding: 10px;
border: 2px solid gray;
margin: 10px;
background: #ffffcc;
}
#org-div-home-and-up
{ text-align: right; font-size: 70%; white-space: nowrap; }
textarea { overflow-x: auto; }
.linenr { font-size: smaller }
.code-highlighted { background-color: #ffff00; }
.org-info-js_info-navigation { border-style: none; }
#org-info-js_console-label
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
.org-info-js_search-highlight
{ background-color: #ffff00; color: #000000; font-weight: bold; }
.org-svg { }
</style>
<link rel="stylesheet" type="text/css" href="mystyle.css" />
</head>
<body>
<div id="content" class="content">
<h1 class="title">Virtuelles Netzwerk mit Open vSwitch</h1>
<div id="orgb2f70a0" class="figure">
<p><img src="img/Ostseepinguin.png" alt="Das Ostseepinguin-Banner zeigt einen Ostseepinguin am Strand." width="100%" />
</p>
</div>
<input type="checkbox" id="darkmode-toggle">
<label for="darkmode-toggle"></label></input>
<script src="script.js"></script>
<div class="menu" id="orgd6f9eba">
<p>
<a href="NetworkNamespace.html">🇺🇸 EN</a>
</p>
<ul class="org-ul">
<li>> <a href="index.DE.html">Home</a></li>
<li>> <a href="NetworkNamespaceDNS.DE.html">Teil II</a></li>
</ul>
<hr />
<p width="16px" alt="Mastodon">
<img src="img/Mastodon.png" alt="Mastodon" width="16px" /> <a href="https://emacs.ch/@SebasTEAan">https://emacs.ch/@SebasTEAan</a>
</p>
<p>
📧 <a href="mailto:sebastian.meisel+ostseepinguin@gmail.com">sebastian.meisel at gmail.com</a>
</p>
</div>
<div id="outline-container-org0ed51c7" class="outline-2">
<h2 id="org0ed51c7">Virtuelles Netzwerk mit Open vSwitch</h2>
<div class="outline-text-2" id="text-org0ed51c7">
<p>
In diesem Projekt möchte ich zeigen, wie ein virtuelles Netzwerk unter Verwendung von Openvswitch und Netzwerknamenräumen unter Linux entworfen und implementiert werden kann. Durch die Nutzung virtueller Ethernet-Tunnel und eines zentralen virtuellen Switches erstellen wir eine flexible und skalierbare Netzwerkumgebung. Mein Hauptziel ist dabei - neben einem besseren Verständnis der Linux-Namenspaces - eine isolierte Netzwerkumgebung zu haben. Als Lehrer möchte ich manchmal meinen Schülern zeigen, wie ein einzelnes Netzwerkprotokoll funktioniert oder was passiert, wenn ich eine Domain pinge. Doch selbst in einer virtuellen Maschine laufen oft viele andere Netzwerkverbindungen im Hintergrund, sodass es schwierig ist, herauszufiltern, woran ich interessiert bin. In der Konfiguration, die ich hier erstelle, ist das einzige Rauschen im virtuellen Netzwerk das IPv6-Router-Solicitation.
</p>
</div>
<div id="outline-container-orge0df834" class="outline-3">
<h3 id="orge0df834">Der Plan</h3>
<div class="outline-text-3" id="text-orge0df834">
<p>
Das folgende Diagramm veranschaulicht die virtuelle Netzwerkkonfiguration, die ich erreichen möchte: Der virtuelle Switch dient als zentraler Punkt und verbindet drei verschiedene Netzwerknamenräume, die durch rot, grün und blau dargestellt sind. Jeder Namespace erhält eine IP-Adresse (<code>eth0-r</code>, <code>eth0-g</code>, <code>eth0-b</code>) innerhalb des Subnetzes <code>10.0.0.0/24</code> und ist über virtuelle Ethernet-Schnittstellen (<code>veth-r</code>, <code>veth-g</code>, <code>veth-b</code>) mit dem vSwitch verbunden.
</p>
<div id="org89f48c8" class="figure">
<p><img src="img/ovs-net.png" alt="Netzwerkschema, das die Beziehung zwischen den Namespacesn gemäß dem obigen Absatz zeigt." width="50%" />
</p>
<p><span class="figure-number">Figure 1: </span>Netzwerkschema</p>
</div>
</div>
</div>
<div id="outline-container-org5fb3752" class="outline-3">
<h3 id="org5fb3752">Funktionen für jeden Namespace erstellen</h3>
<div class="outline-text-3" id="text-org5fb3752">
<p>
Zunächst definieren wir zwei Variablen, um die beabsichtigten Namespaces und ihre zugehörigen Farben einzurichten. Die erste Variable ist eine einfache Indexliste mit den Namen <code>red</code>, <code>green</code> und <code>blue</code>. Die zweite Variable wird mit dem Bash-Befehl <code>declare</code> mit der Option <code>-x</code> für Export und <code>-A</code> für assoziative Liste erstellt. Hier verknüpfen wir Escape-Codes für die Farbausgabe im Terminal mit den farbigen Namespace-Namen. Diese Definition legen wir in der Datei <code>files/ovs_setup.sh</code> ab.
</p>
</div>
<div id="outline-container-org7241834" class="outline-4">
<h4 id="org7241834">Umgebungsvariablen und Farbliste definieren</h4>
<div class="outline-text-4" id="text-org7241834">
<p>
Der folgende Bash-Skript definiert Umgebungsvariablen und eine Farbliste, die für das Einrichten des virtuellen Netzwerks erforderlich sind.
</p>
<div class="org-src-container">
<pre class="src src-bash"><span style="color: #f78fe7;">export</span> <span style="color: #00d3d0;">namespaces</span>=(red green blue)
<span style="color: #f78fe7;">declare</span> -xA <span style="color: #00d3d0;">colorlist</span>=(red <span style="color: #79a8ff;">'\e[31m'</span>
green <span style="color: #79a8ff;">'\e[32m'</span>
orange <span style="color: #79a8ff;">'\e[33m'</span>
blue <span style="color: #79a8ff;">'\e[34m'</span>
magenta <span style="color: #79a8ff;">'\e[35m'</span>
cyan <span style="color: #79a8ff;">'\e[36m'</span>)
</pre>
</div>
<p>
Wir verwenden die <code>source</code>-Funktion, um diese Datei im zweiten Skript <code>files/ovs.sh</code> einzubinden, zu dem wir all den folgenden Code hinzufügen. So können wir dieses Setup leicht reproduzieren und sogar in Zukunft anpassen. Innerhalb dieses Skripts erstellen wir zunächst eine Funktion namens <code>netns()</code>. Sie nimmt einen Namespace-Namen und die auszuführenden Befehle im Namespace als Eingabe entgegen und führt den Befehl im zugewiesenen Namespace aus, wobei die Ausgabe in der Farbe des Namespaces kodiert wird. Auf diese Weise können wir später leicht erkennen, in welchem Namespace ein Befehl ausgeführt wurde.
</p>
<div class="org-src-container">
<pre class="src src-bash"><span style="color: #00d3d0;">script_dir</span>=<span style="color: #79a8ff;">"$(</span><span style="color: #f78fe7;">dirname ${BASH_SOURCE[0]}</span><span style="color: #79a8ff;">)"</span>
<span style="color: #f78fe7;">.</span> ${<span style="color: #00d3d0;">script_dir</span>}/ovs_setup.sh
<span style="color: #b6a0ff;">function</span> <span style="color: #feacd0;">netns</span> () {
<span style="color: #00d3d0;">color</span>=$<span style="color: #00d3d0;">1</span>
<span style="color: #f78fe7;">shift</span>
<span style="color: #00d3d0;">args</span>=$<span style="color: #00d3d0;">@</span>
<span style="color: #b6a0ff;">if</span> [[ ${<span style="color: #00d3d0;">args</span>[0]} = <span style="color: #79a8ff;">"bash"</span> ]]
<span style="color: #b6a0ff;">then</span>
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Zu riskant für meinen Geschmack"</span>
<span style="color: #b6a0ff;">else</span>
<span style="color: #b6a0ff;">if</span> [[ $(<span style="color: #f78fe7;">ip netns list | grep -o ${color}</span>) == ${<span style="color: #00d3d0;">color</span>} ]]
<span style="color: #b6a0ff;">then</span>
<span style="color: #f78fe7;">echo</span> -ne ${<span style="color: #00d3d0;">colorlist</span>[$<span style="color: #00d3d0;">color</span>]}
sudo ip netns exec ${<span style="color: #00d3d0;">color</span>} ${<span style="color: #00d3d0;">args</span>[@]}
<span style="color: #f78fe7;">echo</span> -ne <span style="color: #79a8ff;">'\e[0m'</span>
<span style="color: #b6a0ff;">else</span>
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Namespace ${color} existiert nicht"</span>
<span style="color: #b6a0ff;">fi</span>
<span style="color: #b6a0ff;">fi</span>
}
</pre>
</div>
<p>
Für noch mehr Bequemlichkeit erstellen wir Aliasse für jeden Namespace, sodass ein einfaches <code>red</code>, <code>green</code> oder <code>blue</code> gefolgt von dem Befehl die <code>netns</code>-Funktion für jeden dieser Namespaces aufruft.
</p>
<div class="org-src-container">
<pre class="src src-bash"><span style="color: #b6a0ff;">for</span> ns<span style="color: #b6a0ff;"> in</span> ${<span style="color: #00d3d0;">namespaces</span>[@]}
<span style="color: #b6a0ff;">do</span>
<span style="color: #f78fe7;">alias</span> ${<span style="color: #00d3d0;">ns</span>}=<span style="color: #79a8ff;">"netns ${ns}"</span> && <span style="color: #f78fe7;">alias</span> ${<span style="color: #00d3d0;">ns</span>} && <span style="color: #f78fe7;">export</span> ${<span style="color: #00d3d0;">ns</span>}
<span style="color: #b6a0ff;">done</span>
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-orgc6b6482" class="outline-3">
<h3 id="orgc6b6482">Namespaces erstellen</h3>
<div class="outline-text-3" id="text-orgc6b6482">
<p>
Der nächste Schritt besteht darin, die drei Netzwerk-Namespaces mit den Namen red, green und blue mithilfe des Befehls <code>ip netns add</code> zu initialisieren. Ich verwende eine for-Schleife, um über die Namespace-Namen zu iterieren. So ist es einfacher, später falls erforderlich neue Namespaces hinzuzufügen. Wo nötig, verweise ich mit der Variablen ${ns} darauf.
</p>
<div class="org-src-container">
<pre class="src src-bash"><span style="color: #b6a0ff;">for</span> ns<span style="color: #b6a0ff;"> in</span> ${<span style="color: #00d3d0;">namespaces</span>[@]}
<span style="color: #b6a0ff;">do</span>
<span style="color: #b6a0ff;">if</span> [[ <span style="color: #d0bc00;">!</span> $(<span style="color: #f78fe7;">ip netns list | grep -o ${ns}</span>) == ${<span style="color: #00d3d0;">ns</span>} ]]
<span style="color: #b6a0ff;">then</span>
sudo ip netns add ${<span style="color: #00d3d0;">ns</span>}
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"${ns} Namespace hinzugefügt."</span>
<span style="color: #b6a0ff;">fi</span>
<span style="color: #b6a0ff;">done</span>
ip netns list
sleep 1
</pre>
</div>
<p>
Anschließend wird das Loopback-Gerät in jedem Namespace mithilfe des Befehls <code>ip l dev lo up</code> aktiviert, um eine lokale Kommunikation innerhalb des Namespaces zu ermöglichen.
</p>
<div class="org-src-container">
<pre class="src src-bash"><span style="color: #b6a0ff;">for</span> ns<span style="color: #b6a0ff;"> in</span> ${<span style="color: #00d3d0;">namespaces</span>[@]}
<span style="color: #b6a0ff;">do</span>
netns ${<span style="color: #00d3d0;">ns</span>} ip link set lo up
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Loopback in ${ns} is up."</span>
<span style="color: #b6a0ff;">done</span>
</pre>
</div>
<p>
Schließlich können wir den aktuellen Zustand der Netzwerkschnittstellen in jedem Namespace mithilfe des Befehls <code>ip l</code> überprüfen.
</p>
<div class="org-src-container">
<pre class="src src-bash"><span style="color: #b6a0ff;">for</span> ns<span style="color: #b6a0ff;"> in</span> ${<span style="color: #00d3d0;">namespaces</span>[@]}
<span style="color: #b6a0ff;">do</span>
netns ${<span style="color: #00d3d0;">ns</span>} ip link
<span style="color: #b6a0ff;">done</span>
</pre>
</div>
</div>
</div>
<div id="outline-container-org90a5b8d" class="outline-3">
<h3 id="org90a5b8d">Tunnel erstellen</h3>
<div class="outline-text-3" id="text-org90a5b8d">
<p>
Jetzt erstellen wir virtuelle Ethernet-Tunnel (veth) mit den Namen <code>veth-r</code>, <code>veth-g</code> und <code>veth-b</code>, die jeweils mit einer Schnittstelle in ihrem entsprechenden Netzwerk-Namespace (<code>eth0-r</code>, <code>eth0-g</code>, <code>eth0-b</code>) für die Kommunikation verbunden sind. Diese Tunnel erleichtern die Kommunikation zwischen dem vSwitch und den Netzwerk-Namespaces. Beachte, dass ich in den Gerätenamen nur den ersten Buchstaben verwende, um die Namespaces zu unterscheiden. Hierfür verwende ich den Mechanismus der Variablenersetzung von Bash mit ${ns::1}, um nur den ersten Buchstaben jeder Zeichenkette zu erhalten. Beachte, dass dies eine Bash-Funktion ist, wenn Du eine andere Shell verwendest.
</p>
<div class="org-src-container">
<pre class="src src-bash"><span style="color: #b6a0ff;">for</span> ns<span style="color: #b6a0ff;"> in</span> ${<span style="color: #00d3d0;">namespaces</span>[@]}
<span style="color: #b6a0ff;">do</span>
sudo ip link add veth-${<span style="color: #00d3d0;">ns</span>::1} <span style="color: #f78fe7;">type</span> veth peer eth0-${<span style="color: #00d3d0;">ns</span>::1}
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Verknüpfe veth-${ns} mit eth0-${ns}."</span>
<span style="color: #b6a0ff;">done</span>
</pre>
</div>
</div>
</div>
<div id="outline-container-org63127ce" class="outline-3">
<h3 id="org63127ce">Link in Namespaces platzieren</h3>
<div class="outline-text-3" id="text-org63127ce">
<p>
Nachdem die Tunnel erstellt wurden, ist der nächste Schritt, die Schnittstellen ihren jeweiligen Namespaces zuzuweisen. Dies wird erreicht, indem jedem Endpunkt eines Tunnels (<code>eth0-r</code>, <code>eth0-g</code>, <code>eth0-b</code>) sein entsprechender Namespace (rot, grün, blau) zugeordnet wird.
</p>
<div class="org-src-container">
<pre class="src src-bash"><span style="color: #b6a0ff;">for</span> ns<span style="color: #b6a0ff;"> in</span> ${<span style="color: #00d3d0;">namespaces</span>[@]}
<span style="color: #b6a0ff;">do</span>
sudo ip link set eth0-${<span style="color: #00d3d0;">ns</span>::1} netns ${<span style="color: #00d3d0;">ns</span>}
<span style="color: #b6a0ff;">done</span>
</pre>
</div>
</div>
</div>
<div id="outline-container-orgbbc0753" class="outline-3">
<h3 id="orgbbc0753">IPv4-Adressen hinzufügen</h3>
<div class="outline-text-3" id="text-orgbbc0753">
<p>
Schließlich werden IPv4-Adressen den Schnittstellen in jedem Namespace zugewiesen, um die Netzwerkkommunikation zu ermöglichen. Die IP-Adressen <code>10.0.0.2</code>, <code>10.0.0.3</code> und <code>10.0.0.4</code> mit einer Subnetzmaske <code>/24</code> werden jeweils den Schnittstellen <code>eth0-r</code>, <code>eth0-g</code> und <code>eth0-b</code> zugewiesen. Zusätzlich werden die Schnittstellen aktiviert, um die Netzwerkkonfiguration zu aktivieren.
</p>
<div class="org-src-container">
<pre class="src src-bash"><span style="color: #00d3d0;">ip</span>=1
<span style="color: #b6a0ff;">for</span> ns<span style="color: #b6a0ff;"> in</span> ${<span style="color: #00d3d0;">namespaces</span>[@]}
<span style="color: #b6a0ff;">do</span>
<span style="color: #00d3d0;">ip</span>=$(<span style="color: #f78fe7;">(ip+1</span>))
netns ${<span style="color: #00d3d0;">ns</span>} ip address add 10.0.0.${<span style="color: #00d3d0;">ip</span>}/24 dev eth0-${<span style="color: #00d3d0;">ns</span>::1}
netns ${<span style="color: #00d3d0;">ns</span>} ip link set dev eth0-${<span style="color: #00d3d0;">ns</span>:0:1} up
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Add IP 10.0.0.${ip} to eth0-${ns::1}."</span>
<span style="color: #b6a0ff;">done</span>
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-orgd02a44c" class="outline-2">
<h2 id="orgd02a44c">Virtuellen Switch öffnen</h2>
<div class="outline-text-2" id="text-orgd02a44c">
<p>
Um den virtuellen Switch einzurichten, wird zunächst das Openvswitch-Paket mithilfe des entsprechenden Paketmanagers installiert. Anschließend wird der Dienst <code>ovs-vswitchd</code> gestartet, um den Switch zu verwalten.
</p>
</div>
<div id="outline-container-orgd413a0d" class="outline-3">
<h3 id="orgd413a0d">Installieren</h3>
<div class="outline-text-3" id="text-orgd413a0d">
<div class="org-src-container">
<pre class="src src-bash"><span style="color: #b6a0ff;">if</span> [ -f /etc/os-release ]; <span style="color: #b6a0ff;">then</span>
<span style="color: #f78fe7;">.</span> /etc/os-release
<span style="color: #b6a0ff;">else</span>
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Die Linux-Distribution kann nicht bestimmt werden."</span>
<span style="color: #b6a0ff;">exit</span> 1
<span style="color: #b6a0ff;">fi</span>
<span style="color: #b6a0ff;">case</span> $<span style="color: #00d3d0;">ID_LIKE</span><span style="color: #b6a0ff;"> in</span>
debian|ubuntu)
sudo apt install -y openvswitch-switch
;;
fedora|rhel|centos)
sudo yum install -y openvswitch
;;
suse)
sudo zypper install -y openvswitch
;;
arch)
sudo pacman -Syu openvswitch
;;
*)
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Nicht unterstützte Distribution."</span>
<span style="color: #b6a0ff;">exit</span> 1
;;
<span style="color: #b6a0ff;">esac</span>
<span style="color: #b6a0ff;">if</span> [[ $<span style="color: #00d3d0;">ID</span> == arch ]]; <span style="color: #b6a0ff;">then</span>
sudo pacman -Syu openvswitch
<span style="color: #b6a0ff;">else</span>
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Nicht unterstützte Distribution."</span>
<span style="color: #b6a0ff;">exit</span> 1
<span style="color: #b6a0ff;">fi</span>
</pre>
</div>
<div class="org-src-container">
<pre class="src src-bash">sudo systemctl start ovs-vswitchd.service
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"ovs-vswitchd gestartet"</span>
</pre>
</div>
</div>
</div>
<div id="outline-container-org7686a57" class="outline-3">
<h3 id="org7686a57">Switch hinzufügen</h3>
<div class="outline-text-3" id="text-org7686a57">
<p>
Nach der Installation erstelle ich einen virtuellen Switch mit dem Namen SW1 mithilfe des Befehls <code>ovs-vsctl add-br</code>.
</p>
<div class="org-src-container">
<pre class="src src-bash">sudo ovs-vsctl add-br SW1
</pre>
</div>
<p>
Die Switch-Konfiguration wird mithilfe von <code>ovs-vsctl show</code> angezeigt.
</p>
<div class="org-src-container">
<pre class="src src-bash">sudo ovs-vsctl show
</pre>
</div>
</div>
<div id="outline-container-org89506f0" class="outline-4">
<h4 id="org89506f0">Ports hinzufügen</h4>
<div class="outline-text-4" id="text-org89506f0">
<p>
Als Nächstes fügen wir Ports zum virtuellen Switch hinzu, um ihn mit den Netzwerk-Namespaces zu verbinden. Jeder Port ist mit einer entsprechenden Tunnel-Schnittstelle (<code>veth-r</code>, <code>veth-g</code>, <code>veth-b</code>) verbunden.
</p>
<div class="org-src-container">
<pre class="src src-bash"><span style="color: #b6a0ff;">for</span> ns<span style="color: #b6a0ff;"> in</span> {r,g,b}
<span style="color: #b6a0ff;">do</span>
sudo ovs-vsctl add-port SW1 veth-${<span style="color: #00d3d0;">ns</span>}
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"veth-${ns} zu SW1 hinzugefügt."</span>
<span style="color: #b6a0ff;">done</span>
</pre>
</div>
<p>
Erneut können wir bestätigen, dass alles wie beabsichtigt funktioniert hat:
</p>
<div class="org-src-container">
<pre class="src src-bash">sudo ovs-vsctl show
</pre>
</div>
<p>
Diese Ports müssen nun aktiviert werden.
</p>
<div class="org-src-container">
<pre class="src src-bash"><span style="color: #b6a0ff;">for</span> ns<span style="color: #b6a0ff;"> in</span> {r,g,b}
<span style="color: #b6a0ff;">do</span>
sudo ip link set veth-${<span style="color: #00d3d0;">ns</span>} up
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Link veth-{ns} ist aktiviert."</span>
<span style="color: #b6a0ff;">done</span>
</pre>
</div>
<p>
Ich überprüfe immer gerne noch einmal. Daher 'grepe' ich nach der <code>veth</code>-Schnittstelle und verwende die <code>-A</code>-Option, um immer die ersten 3 Zeilen jeder Schnittstellenkonfiguration anzuzeigen.
</p>
<div class="org-src-container">
<pre class="src src-bash">sudo ip a | grep veth -A3
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-org726c75e" class="outline-3">
<h3 id="org726c75e">Aufräumen</h3>
<div class="outline-text-3" id="text-org726c75e">
<p>
Ein Neustart wird in der Regel den Großteil des Chaos hinter uns aufräumen, aber ich möchte ein gutes Kind sein und selbst aufräumen. Daher habe ich ein weiteres Skript erstellt, das genau das tut.
</p>
<div class="org-src-container">
<pre class="src src-bash"><span style="color: #00d3d0;">script_dir</span>=<span style="color: #79a8ff;">"$(</span><span style="color: #f78fe7;">dirname ${BASH_SOURCE[0]}</span><span style="color: #79a8ff;">)"</span>
<span style="color: #a8a8a8;">#</span><span style="color: #a8a8a8;">Source Setup</span>
<span style="color: #f78fe7;">.</span> ${<span style="color: #00d3d0;">script_dir</span>}/ovs_setup.sh
<span style="color: #a8a8a8;"># </span><span style="color: #a8a8a8;">Create a list of target interfaces</span>
<span style="color: #b6a0ff;">for</span> ns<span style="color: #b6a0ff;"> in</span> ${<span style="color: #00d3d0;">namespaces</span>[@]}
<span style="color: #b6a0ff;">do</span>
<span style="color: #00d3d0;">target_interfaces</span>=(${<span style="color: #00d3d0;">target_interfaces</span>[@]} veth-${<span style="color: #00d3d0;">ns</span>::1})
<span style="color: #b6a0ff;">done</span>
<span style="color: #a8a8a8;"># </span><span style="color: #a8a8a8;">Überprüfen Sie auf vorhandene Namespaces</span>
<span style="color: #b6a0ff;">if</span> [[ -n $(<span style="color: #f78fe7;">ip netns list</span>) ]]; <span style="color: #b6a0ff;">then</span>
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Netzwerk-Namespaces werden entfernt..."</span>
<span style="color: #a8a8a8;"># </span><span style="color: #a8a8a8;">Durchlaufen Sie jeden Namespace und entfernen Sie nur passende</span>
<span style="color: #b6a0ff;">for</span> ns<span style="color: #b6a0ff;"> in</span> $(<span style="color: #f78fe7;">ip netns list | awk '{print $1}'</span>); <span style="color: #b6a0ff;">do</span>
<span style="color: #b6a0ff;">if</span> [[ <span style="color: #79a8ff;">"${namespaces[@]}"</span> =~ <span style="color: #79a8ff;">"$ns"</span> ]]; <span style="color: #b6a0ff;">then</span>
sudo ip netns del $<span style="color: #00d3d0;">ns</span>
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Namespace entfernt: $ns"</span>
<span style="color: #b6a0ff;">fi</span>
<span style="color: #b6a0ff;">done</span>
<span style="color: #b6a0ff;">else</span>
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Keine Netzwerk-Namespaces gefunden."</span>
<span style="color: #b6a0ff;">fi</span>
<span style="color: #a8a8a8;"># </span><span style="color: #a8a8a8;">Überprüfen Sie auf vorhandene veth-Schnittstellen</span>
<span style="color: #b6a0ff;">if</span> [[ $(<span style="color: #f78fe7;">ip link show | grep veth -c</span>) -gt 0 ]]; <span style="color: #b6a0ff;">then</span>
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Veth-Schnittstellen werden entfernt..."</span>
<span style="color: #a8a8a8;"># </span><span style="color: #a8a8a8;">Durchlaufen Sie jede veth-Schnittstelle und entfernen Sie nur passende</span>
<span style="color: #b6a0ff;">for</span> veth<span style="color: #b6a0ff;"> in</span> $(<span style="color: #f78fe7;">ip link show | grep veth | awk '{print $2}' |sed 's/@.*$//g'</span>); <span style="color: #b6a0ff;">do</span>
<span style="color: #b6a0ff;">if</span> [[ <span style="color: #79a8ff;">"${target_interfaces[@]}"</span> =~ <span style="color: #79a8ff;">"$veth"</span> ]]; <span style="color: #b6a0ff;">then</span>
sudo ip link del $<span style="color: #00d3d0;">veth</span>
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Schnittstelle entfernt: $veth"</span>
<span style="color: #b6a0ff;">fi</span>
<span style="color: #b6a0ff;">done</span>
<span style="color: #b6a0ff;">else</span>
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Keine veth-Schnittstellen gefunden."</span>
<span style="color: #b6a0ff;">fi</span>
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Open vSwitch wird gestoppt und deaktiviert..."</span>
sudo systemctl stop ovs-vswitchd.service
<span style="color: #a8a8a8;"># </span><span style="color: #a8a8a8;">Überprüfen, ob das benannte Ausführungsverzeichnis für den blauen Namespace vorhanden ist</span>
<span style="color: #b6a0ff;">if</span> [[ -d $(<span style="color: #f78fe7;">ls -d blue_named_run_?????</span>) ]]; <span style="color: #b6a0ff;">then</span>
rm -rf blue_named_run_?????
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Ausführungsverzeichnis für den benannten Dienst im blauen Namespace entfernt"</span>.
<span style="color: #b6a0ff;">fi</span>
<span style="color: #b6a0ff;">for</span> ns<span style="color: #b6a0ff;"> in</span> ${<span style="color: #00d3d0;">namespaces</span>[@]}
<span style="color: #b6a0ff;">do</span>
<span style="color: #b6a0ff;">if</span> [[ $(<span style="color: #f78fe7;">alias ${ns}</span>) ]] ; <span style="color: #b6a0ff;">then</span>
<span style="color: #f78fe7;">unalias</span> ${<span style="color: #00d3d0;">ns</span>}
<span style="color: #79a8ff;">"${ns} entaliasiert."</span>
<span style="color: #b6a0ff;">fi</span>
<span style="color: #b6a0ff;">done</span>
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Unseting netns function and variables"</span>
<span style="color: #f78fe7;">unset</span> -f netns
<span style="color: #f78fe7;">unset</span> namespaces
<span style="color: #f78fe7;">unset</span> colorlist
<span style="color: #f78fe7;">echo</span> <span style="color: #79a8ff;">"Aufräumen abgeschlossen!"</span>
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-orgddf5daf" class="outline-2">
<h2 id="orgddf5daf">Fazit</h2>
<div class="outline-text-2" id="text-orgddf5daf">
<p>
Es ist überraschend einfach, dieses grundlegende Setup zu erstellen.
</p>
<p>
Wir können jetzt die verschiedenen Namespaces erkunden, indem wir netzwerkbezogene Befehle mit den <code>red()</code>, <code>blue()</code> und <code>green()</code> Funktionen aufrufen, z. B.:
</p>
<div class="org-src-container">
<pre class="src src-bash">sudo blue ip route
sudo red ping 10.0.0.3 -c 5
sudo green nstat -s | grep -i icmp
</pre>
</div>
<p>
Dies ist ein großartiger Spielplatz, um grundlegende Netzwerkfunktionalitäten zu erkunden.
</p>
</div>
</div>
<div id="outline-container-org296e403" class="outline-2">
<h2 id="org296e403">Anerkennung</h2>
<div class="outline-text-2" id="text-org296e403">
<p>
Ich habe über Netzwerk-Namespaces in zwei fantastischen Videos gelernt:
</p>
<ul class="org-ul">
<li><a href="https://www.youtube.com/watch?v=_WgUwUf1d34&t=940s">Introduction to Linux Network Namespaces by David Mahler (YouTube)</a></li>
<li><a href="https://www.youtube.com/watch?v=iN2RnYaFn-0">Linux Network Namespaces with ip netns by Andrew Mallet (YouTube)</a></li>
</ul>
</div>
</div>
</div>
<div id="postamble" class="status">
<p class="date">Date: 2024-02-24 Sa 00:00</p>
<p class="author">Author: Sebastian Meisel</p>
<p class="date">Created: 2024-02-29 Do 11:18</p>
<p class="validation"><a href="https://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
</body>
</html>