-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathschema_reseau.html
More file actions
684 lines (656 loc) · 39.8 KB
/
Copy pathschema_reseau.html
File metadata and controls
684 lines (656 loc) · 39.8 KB
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
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Schéma réseau d'entreprise</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
:root{--bg:#f8fafc;--card:#fff;--border:#e2e8f0;--text:#1e293b;--muted:#64748b;--acc:#0891b2;--acc2:#0e7490;--blue600:#2563eb;--green:#16a34a;--red:#dc2626;--orange:#ea580c;--purple:#7c3aed;--grad1:#083344;--grad2:#155e75;
--bg2:#f7f7f5;--bg3:#ededea;--text3:#9b9b94;--border2:rgba(0,0,0,0.18);
--blue50:#E6F1FB;--blue100:#B5D4F4;--blue200:#85B7EB;--blue800:#0C447C;
--teal50:#E1F5EE;--teal600:#0F6E56;--teal800:#085041;
--amber50:#FAEEDA;--amber600:#854F0B;--amber800:#633806;
--purple50:#EEEDFE;--purple600:#534AB7;--purple800:#3C3489;
--green50:#EAF3DE;--green600:#3B6D11;
--coral50:#FAECE7;--coral600:#993C1D;--coral800:#712B13;
--rad:8px;--rad-lg:12px}
@media(prefers-color-scheme:dark){:root{--bg:#0d0d0d;--card:#1a1a1a;--border:#2a2a2a;--text:#e2e8f0;--muted:#94a3b8;
--bg2:#272724;--bg3:#2e2e2b;--text3:#6b6b65;--border2:rgba(255,255,255,0.18);
--blue50:#0c2540;--blue200:#85B7EB;--blue800:#B5D4F4;
--teal50:#052e1f;--teal600:#5DCAA5;--teal800:#9FE1CB;
--amber50:#2a1a04;--amber600:#EF9F27;--amber800:#FAC775;
--purple50:#1a1640;--purple600:#AFA9EC;--purple800:#CECBF6;
--green50:#0f2005;--green600:#97C459;
--coral50:#2a0e06;--coral600:#F0997B;--coral800:#F5C4B3}}
body{font-family:'Segoe UI',system-ui,sans-serif;background:var(--bg);color:var(--text);font-size:14px;line-height:1.6;padding-bottom:40px}
header{background:linear-gradient(135deg,var(--grad1),var(--grad2));padding:2rem 1rem;text-align:center;border-bottom:2px solid var(--acc)}
header h1{font-size:2rem;font-weight:800;color:#fff}
header p{color:#67e8f9;margin-top:.4rem;font-size:.95rem;max-width:820px;margin-left:auto;margin-right:auto}
.card{background:var(--card);border:1px solid var(--border);border-radius:.75rem;padding:1.2rem}
.card h4{font-size:1rem;font-weight:700;margin-bottom:.5rem;color:var(--acc)}
table{width:100%;border-collapse:collapse;font-size:.85rem;margin:.5rem 0}
th{background:var(--acc);color:#fff;padding:.5rem .75rem;text-align:left}
td{padding:.45rem .75rem;border-bottom:1px solid var(--border)}
tr:hover td{background:var(--border)}
.info-box{background:var(--card);border-left:4px solid var(--acc);border-radius:.5rem;padding:.8rem 1rem;margin:.5rem 0}
.info-box.green{border-color:var(--green)}.info-box.red{border-color:var(--red)}.info-box.blue{border-color:var(--blue600)}.info-box.orange{border-color:var(--orange)}.info-box.purple{border-color:var(--purple)}
.badge{display:inline-block;padding:.2rem .6rem;border-radius:999px;font-size:.75rem;font-weight:600;margin:.1rem}
.badge-blue{background:#dbeafe;color:#1d4ed8}.badge-green{background:#dcfce7;color:#15803d}
.badge-red{background:#fee2e2;color:#b91c1c}.badge-yellow{background:#fef3c7;color:#92400e}
.badge-purple{background:#ede9fe;color:#6d28d9}.badge-indigo{background:#e0e7ff;color:#3730a3}
@media(prefers-color-scheme:dark){.badge-blue{background:#1e3a5f;color:#93c5fd}.badge-green{background:#14532d;color:#86efac}.badge-red{background:#450a0a;color:#fca5a5}.badge-yellow{background:#451a03;color:#fcd34d}.badge-purple{background:#2e1065;color:#c4b5fd}.badge-indigo{background:#1e1b4b;color:#a5b4fc}}
/* ─── Schéma réseau : layout, nœuds, liens, panneau ─── */
.page-wrap{max-width:980px;margin:0 auto;padding:20px 16px}
.diagram-scroll{overflow-x:auto;border:0.5px solid var(--border);border-radius:var(--rad-lg);background:var(--bg)}
#main-svg{display:block}
/* Device nodes */
.dev{cursor:pointer}
.dev-bg{transition:filter .12s}
.dev:hover .dev-bg{filter:brightness(1.08)}
.dev.sel .dev-bg{stroke-width:2.5}
.dev-icon{text-anchor:middle;dominant-baseline:central;font-size:15px;pointer-events:none}
.dev-name{text-anchor:middle;font-size:8.5px;pointer-events:none;font-weight:500}
.dev-sub{text-anchor:middle;font-size:7.5px;pointer-events:none;opacity:.7}
/* Links */
.lk{fill:none}
.lk-wan {stroke:#185FA5;stroke-opacity:.75;stroke-width:2}
.lk-main {stroke:#0F6E56;stroke-opacity:.7;stroke-width:1.8}
.lk-dmz {stroke:#854F0B;stroke-opacity:.75;stroke-width:1.8}
.lk-vpn {stroke:#534AB7;stroke-opacity:.75;stroke-width:1.8;stroke-dasharray:6,3}
.lk-ha {stroke:#993C1D;stroke-opacity:.65;stroke-width:1.5;stroke-dasharray:4,3}
.lk-vsl {stroke:#185FA5;stroke-opacity:.9;stroke-width:2.8}
.lk-lacp {stroke:#0F6E56;stroke-opacity:.75;stroke-width:2}
.lk-access {stroke:#3B6D11;stroke-opacity:.6;stroke-width:1.5}
.lk-wifi {stroke:#3B6D11;stroke-opacity:.55;stroke-width:1.5;stroke-dasharray:4,2}
.lk-mgmt {stroke:#9b9b94;stroke-opacity:.7;stroke-width:1.3;stroke-dasharray:3,3}
.lk-backup {stroke:#9b9b94;stroke-opacity:.5;stroke-width:1.3;stroke-dasharray:6,4}
.lk-end {stroke:#9b9b94;stroke-opacity:.45;stroke-width:1.2}
.lk-label {font-size:7.5px;fill:var(--text3);text-anchor:middle;pointer-events:none;dominant-baseline:central}
.zone-lbl {font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;pointer-events:none}
/* Info panel */
#info-panel{margin-top:16px;border:0.5px solid var(--border);border-radius:var(--rad-lg);padding:14px 16px;min-height:80px;background:var(--card)}
#info-panel .ip-title{font-size:15px;font-weight:500;margin-bottom:8px}
#info-panel .ip-zone{font-size:11px;padding:2px 8px;border-radius:20px;font-weight:500;display:inline-block;margin-left:8px}
.ip-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:8px;margin:10px 0}
.ip-block{background:var(--bg2);border-radius:var(--rad);padding:8px 10px}
.ip-block-title{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--text3);margin-bottom:4px}
.ip-block-val{font-size:12px;color:var(--muted);line-height:1.6}
.ip-neighbors{display:flex;flex-wrap:wrap;gap:5px;margin-top:8px}
.nb-tag{font-size:11px;padding:2px 8px;border-radius:20px;background:var(--bg2);border:0.5px solid var(--border2);color:var(--muted);cursor:pointer}
.nb-tag:hover{background:var(--blue50);border-color:var(--blue200);color:var(--blue800)}
/* Legend */
.legend{margin-top:12px;display:flex;flex-wrap:wrap;gap:8px 16px;font-size:12px;color:var(--muted);padding:0 2px}
.leg-item{display:flex;align-items:center;gap:6px}
.leg-line{width:28px;height:2px;border-radius:1px}
</style>
</head>
<body>
<header>
<h1>Schéma réseau d'entreprise</h1>
<p>Cliquez sur un équipement pour afficher ses détails · Les interfaces et adresses IP sont indiquées sur les liens</p>
</header>
<div class="page-wrap">
<div class="diagram-scroll">
<svg id="main-svg" viewBox="0 0 900 690" width="900" height="690" xmlns="http://www.w3.org/2000/svg"></svg>
</div>
<div id="info-panel"><span style="color:var(--text3);font-size:13px">Cliquez sur un équipement pour afficher ses détails.</span></div>
<div class="legend" id="legend"></div>
</div>
<script>
// ─── Zone backgrounds ───────────────────────────────────────────────────────
const ZONES = [
{ id:'internet', label:'Internet / WAN', x:0, y:0, w:900, h:63, color:'#185FA5', labelX:12, labelY:14 },
{ id:'operateur', label:'Équipement opérateur (CPE)', x:0, y:63, w:900, h:72, color:'#6b6b65', labelX:12, labelY:77 },
{ id:'perimetre', label:'Zone périmètre — Pare-feu & VPN', x:0, y:135, w:900, h:90, color:'#993C1D', labelX:12, labelY:149 },
{ id:'dmz', label:'DMZ', x:578, y:225, w:322, h:200, color:'#854F0B', labelX:590, labelY:239 },
{ id:'core', label:'Cœur de réseau (Layer 3)', x:0, y:225, w:578, h:113, color:'#0F6E56', labelX:12, labelY:239 },
{ id:'distrib', label:'Distribution (Layer 2/3)', x:0, y:338, w:578, h:110, color:'#0F6E56', labelX:12, labelY:352 },
{ id:'access', label:'Accès (Layer 2)', x:0, y:448, w:578, h:97, color:'#0F6E56', labelX:12, labelY:462 },
{ id:'users', label:'Terminaux & utilisateurs', x:0, y:545, w:578, h:145, color:'#3B6D11', labelX:12, labelY:559 },
{ id:'servers', label:'Zone serveurs (VLAN 40)', x:578, y:425, w:322, h:265, color:'#534AB7', labelX:590, labelY:439 },
];
// ─── Devices (x,y = center) ─────────────────────────────────────────────────
const DEVS = {
internet: { x:450, y:32, icon:'🌐', label:'Internet/WAN', sub:'', type:'cloud', zone:'internet', fill:'#ddeeff', stroke:'#185FA5' },
cpe: { x:450, y:100, icon:'🔌', label:'CPE Opérateur', sub:'(Cisco ISR)', type:'router', zone:'operateur', fill:'#e8e8e4', stroke:'#6b6b65' },
vpn_gw: { x:175, y:180, icon:'🔐', label:'VPN Gateway', sub:'IKEv2/SSL', type:'security', zone:'perimetre', fill:'#f0eefe', stroke:'#534AB7' },
fw01: { x:340, y:180, icon:'🔥', label:'FW-01', sub:'Active', type:'firewall', zone:'perimetre', fill:'#fce8e4', stroke:'#993C1D' },
fw02: { x:480, y:180, icon:'🔥', label:'FW-02', sub:'Passive/HA', type:'firewall', zone:'perimetre', fill:'#fce8e4', stroke:'#993C1D' },
dmz_proxy: { x:700, y:272, icon:'🔄', label:'Rev.Proxy/WAF', sub:'VLAN 50', type:'server', zone:'dmz', fill:'#faeeda', stroke:'#854F0B' },
dmz_web: { x:790, y:348, icon:'🌐', label:'Web Server', sub:'VLAN 50', type:'server', zone:'dmz', fill:'#faeeda', stroke:'#854F0B' },
dmz_mail: { x:614, y:348, icon:'✉️', label:'Mail Relay', sub:'VLAN 50', type:'server', zone:'dmz', fill:'#faeeda', stroke:'#854F0B' },
core_a: { x:225, y:282, icon:'🔀', label:'Core-SW-A', sub:'(L3/VSS)', type:'switch', zone:'core', fill:'#e1f5ee', stroke:'#0F6E56' },
core_b: { x:385, y:282, icon:'🔀', label:'Core-SW-B', sub:'(L3/VSS)', type:'switch', zone:'core', fill:'#e1f5ee', stroke:'#0F6E56' },
srv_sw: { x:520, y:282, icon:'🔀', label:'Srv-Switch', sub:'(L2)', type:'switch', zone:'core', fill:'#e1f5ee', stroke:'#0F6E56' },
dist1: { x:118, y:390, icon:'🔀', label:'Dist-SW-1', sub:'Bâtiment A', type:'switch', zone:'distrib', fill:'#e8f4ea', stroke:'#3B6D11' },
dist2: { x:320, y:390, icon:'🔀', label:'Dist-SW-2', sub:'Bâtiment B', type:'switch', zone:'distrib', fill:'#e8f4ea', stroke:'#3B6D11' },
acc11: { x:62, y:475, icon:'🔀', label:'Acc-SW-1.1', sub:'Rdc Bât.A', type:'switch', zone:'access', fill:'#f0faf2', stroke:'#3B6D11' },
acc12: { x:170, y:475, icon:'🔀', label:'Acc-SW-1.2', sub:'R1 Bât.A', type:'switch', zone:'access', fill:'#f0faf2', stroke:'#3B6D11' },
acc21: { x:268, y:475, icon:'🔀', label:'Acc-SW-2.1', sub:'Rdc Bât.B', type:'switch', zone:'access', fill:'#f0faf2', stroke:'#3B6D11' },
acc22: { x:368, y:475, icon:'🔀', label:'Acc-SW-2.2', sub:'R1 Bât.B', type:'switch', zone:'access', fill:'#f0faf2', stroke:'#3B6D11' },
wap: { x:484, y:475, icon:'📡', label:'WiFi AP (×6)', sub:'802.11ax', type:'wireless', zone:'access', fill:'#eaf3de', stroke:'#3B6D11' },
users_a: { x:116, y:590, icon:'💻', label:'Postes Bât.A', sub:'VLAN 20', type:'endpoint', zone:'users', fill:'#f5f5f3', stroke:'#9b9b94' },
voip: { x:268, y:590, icon:'📞', label:'VoIP Bât.B', sub:'VLAN 30', type:'endpoint', zone:'users', fill:'#f5f5f3', stroke:'#9b9b94' },
printers: { x:368, y:590, icon:'🖨️', label:'Imprimantes', sub:'VLAN 20', type:'endpoint', zone:'users', fill:'#f5f5f3', stroke:'#9b9b94' },
guests: { x:484, y:590, icon:'📱', label:'Invités WiFi', sub:'VLAN 60', type:'endpoint', zone:'users', fill:'#f5f5f3', stroke:'#9b9b94' },
ad_dc: { x:630, y:458, icon:'🗄️', label:'AD / DC (×2)', sub:'VLAN 40', type:'server', zone:'servers', fill:'#eeedfe', stroke:'#534AB7' },
infra_srv: { x:730, y:458, icon:'🗄️', label:'DNS·DHCP·NTP', sub:'VLAN 40', type:'server', zone:'servers', fill:'#eeedfe', stroke:'#534AB7' },
siem: { x:828, y:458, icon:'📊', label:'SIEM/Syslog', sub:'VLAN 40', type:'server', zone:'servers', fill:'#eeedfe', stroke:'#534AB7' },
file_db: { x:680, y:533, icon:'🗄️', label:'Fichiers/BD', sub:'VLAN 40', type:'server', zone:'servers', fill:'#eeedfe', stroke:'#534AB7' },
backup: { x:790, y:533, icon:'💾', label:'Sauvegarde', sub:'VLAN 40', type:'server', zone:'servers', fill:'#eeedfe', stroke:'#534AB7' },
};
// ─── Links ──────────────────────────────────────────────────────────────────
const LINKS = [
// WAN / Internet
{ a:'internet', b:'cpe', cls:'lk-wan', label:'203.0.113.0/30', lox:12, loy:-6 },
{ a:'cpe', b:'fw01', cls:'lk-wan', label:'Gi0/1 — WAN', lox:14, loy:-4 },
{ a:'cpe', b:'fw02', cls:'lk-wan', label:'Gi0/2 — WAN', lox:-14, loy:-4 },
// VPN
{ a:'vpn_gw', b:'fw01', cls:'lk-vpn', label:'IKEv2 tunnel', lox:0, loy:-7 },
{ a:'vpn_gw', b:'core_a', cls:'lk-vpn', label:'10.10.0.0/24', lox:-18, loy:0 },
// HA
{ a:'fw01', b:'fw02', cls:'lk-ha', label:'HA Sync / VRRP', lox:0, loy:-7 },
// FW → DMZ
{ a:'fw01', b:'dmz_proxy', cls:'lk-dmz', label:'DMZ 10.0.50.0/24', lox:18, loy:-6 },
{ a:'dmz_proxy',b:'dmz_web', cls:'lk-dmz', label:'HTTPS', lox:10, loy:-5 },
{ a:'dmz_proxy',b:'dmz_mail', cls:'lk-dmz', label:'SMTP', lox:-10, loy:-5 },
// FW → Core (main paths)
{ a:'fw01', b:'core_a', cls:'lk-main', label:'10.0.0.0/30 Trunk',lox:-18, loy:0 },
{ a:'fw02', b:'core_b', cls:'lk-backup', label:'(failover)', lox:14, loy:0 },
// Core VSL / interconnect
{ a:'core_a', b:'core_b', cls:'lk-vsl', label:'VSL 40G', lox:0, loy:-8 },
{ a:'core_b', b:'srv_sw', cls:'lk-vsl', label:'LACP 10G', lox:0, loy:-8 },
// Core → Distribution
{ a:'core_a', b:'dist1', cls:'lk-lacp', label:'LACP Trunk', lox:-14, loy:0 },
{ a:'core_b', b:'dist2', cls:'lk-lacp', label:'LACP Trunk', lox:10, loy:0 },
// Distribution → Access
{ a:'dist1', b:'acc11', cls:'lk-access', label:'V20,30', lox:-10, loy:0 },
{ a:'dist1', b:'acc12', cls:'lk-access', label:'V20', lox:10, loy:0 },
{ a:'dist2', b:'acc21', cls:'lk-access', label:'V30', lox:-10, loy:0 },
{ a:'dist2', b:'acc22', cls:'lk-access', label:'V20', lox:10, loy:0 },
{ a:'dist2', b:'wap', cls:'lk-wifi', label:'V20,60', lox:14, loy:0 },
// Access → Endpoints
{ a:'acc11', b:'users_a', cls:'lk-end', label:'', lox:0, loy:0 },
{ a:'acc12', b:'users_a', cls:'lk-end', label:'', lox:0, loy:0 },
{ a:'acc21', b:'voip', cls:'lk-end', label:'', lox:0, loy:0 },
{ a:'acc22', b:'printers', cls:'lk-end', label:'', lox:0, loy:0 },
{ a:'wap', b:'guests', cls:'lk-wifi', label:'SSID Invités', lox:16, loy:0 },
// Srv-Switch → Servers
{ a:'srv_sw', b:'ad_dc', cls:'lk-main', label:'VLAN 40', lox:10, loy:-5 },
{ a:'srv_sw', b:'infra_srv', cls:'lk-main', label:'VLAN 40', lox:16, loy:0 },
{ a:'srv_sw', b:'siem', cls:'lk-mgmt', label:'Mgmt/Logs', lox:18, loy:5 },
{ a:'srv_sw', b:'file_db', cls:'lk-main', label:'VLAN 40', lox:10, loy:5 },
{ a:'srv_sw', b:'backup', cls:'lk-backup', label:'Backup', lox:18, loy:5 },
];
// ─── Device info ────────────────────────────────────────────────────────────
const DEV_INFO = {
internet: {
title:'Internet / WAN',
zone:'Internet',
zoneCls:'style="background:var(--blue50);color:var(--blue800)"',
ip:'203.0.113.0/30 (lien vers CPE)',
role:'Réseau étendu mondial. Source de tout trafic entrant, destination du trafic sortant. Zone non fiable.',
interfaces:['Lien FAI A — fibre 1 Gbps','Lien FAI B — 4G/ADSL (secours)'],
protocols:'BGP, HTTP, HTTPS, SMTP, DNS',
notes:'Toujours considéré comme UNTRUSTED. Aucun flux non initié autorisé vers l\'intérieur.',
neighbors:['cpe'],
},
cpe: {
title:'Routeur CPE Opérateur',
zone:'Opérateur',
zoneCls:'style="background:var(--bg2);color:var(--muted)"',
ip:'Gi0/0 : 203.0.113.1/30 (WAN) | Gi0/1 : 203.0.113.5/30 → FW-01 | Gi0/2 : 203.0.113.9/30 → FW-02',
role:'Équipement de terminaison du lien opérateur (CPE). Routage statique vers les deux pare-feux.',
interfaces:['Gi0/0 — WAN opérateur (fibre)','Gi0/1 — vers FW-01 Active','Gi0/2 — vers FW-02 Passive'],
protocols:'BGP (ou route statique), IP SLA',
notes:'Fourni et géré par l\'opérateur. Deux liens vers les FW pour la redondance de périmètre.',
neighbors:['internet','fw01','fw02'],
},
vpn_gw: {
title:'VPN Gateway',
zone:'Zone Périmètre',
zoneCls:'style="background:var(--purple50);color:var(--purple800)"',
ip:'WAN : 203.0.113.20/32 (VIP) | LAN : 10.0.0.10/30 | Pool VPN : 10.10.0.0/24',
role:'Concentrateur VPN pour les accès distants (SSL VPN / IKEv2) et les tunnels site-à-site.',
interfaces:['eth0 — WAN (public)','eth1 — LAN (vers core)'],
protocols:'IKEv2/IPsec, SSL VPN (TLS 1.3), RADIUS, LDAP',
notes:'Auth via RADIUS → Active Directory (MFA obligatoire). Split tunneling configurable. Logs vers SIEM.',
neighbors:['fw01','core_a'],
},
fw01: {
title:'FW-01 — Pare-feu Actif',
zone:'Zone Périmètre',
zoneCls:'style="background:var(--coral50);color:var(--coral800)"',
ip:'WAN : 203.0.113.6/30 | LAN : 10.0.0.1/30 | DMZ : 10.0.50.1/24 | Mgmt : 10.0.10.1',
role:'Pare-feu principal en mode ACTIF. Filtrage stateful, NAT/PAT, segmentation des zones, IPS inline.',
interfaces:['Gi0/0 — WAN (vers CPE)','Gi0/1 — LAN Trunk (vers Core-SW-A)','Gi0/2 — DMZ (vers Rev.Proxy)','Gi0/3 — HA Sync (vers FW-02)'],
protocols:'Stateful firewall, NAT, IPsec, OSPF, VRRP, SNMP, Syslog',
notes:'Politique "deny all" par défaut. Synchronisation d\'état avec FW-02 (VRRP). Basculement < 3 secondes.',
neighbors:['cpe','fw02','vpn_gw','dmz_proxy','core_a'],
},
fw02: {
title:'FW-02 — Pare-feu Passif (HA)',
zone:'Zone Périmètre',
zoneCls:'style="background:var(--coral50);color:var(--coral800)"',
ip:'WAN : 203.0.113.10/30 | LAN : 10.0.0.5/30 | Mgmt : 10.0.10.2',
role:'Pare-feu secondaire en mode PASSIF. En veille, synchronise son état avec FW-01. Prend le relais automatiquement en cas de panne.',
interfaces:['Gi0/0 — WAN (vers CPE)','Gi0/1 — LAN Trunk (vers Core-SW-B)','Gi0/3 — HA Sync (vers FW-01)'],
protocols:'Stateful failover, VRRP, Syslog',
notes:'Aucun trafic en temps normal. Tous les flux passent par FW-01. Bascule automatique sur défaillance.',
neighbors:['cpe','fw01','core_b'],
},
dmz_proxy: {
title:'Reverse Proxy / WAF',
zone:'DMZ',
zoneCls:'style="background:var(--amber50);color:var(--amber800)"',
ip:'10.0.50.5/24 (DMZ) | VIP publique : 203.0.113.30',
role:'Reverse proxy HTTP(S) et Web Application Firewall. Point d\'entrée unique pour tout le trafic web entrant. Terminaison TLS.',
interfaces:['eth0 — DMZ (10.0.50.0/24)'],
protocols:'HTTP/1.1, HTTP/2, TLS 1.3, OWASP ModSecurity',
notes:'Terminaison TLS (certificat wildcard). Ré-chiffrement vers les backends. Protection XSS, SQLi, CSRF. Rate limiting, caching.',
neighbors:['fw01','dmz_web','dmz_mail'],
},
dmz_web: {
title:'Serveur Web (DMZ)',
zone:'DMZ',
zoneCls:'style="background:var(--amber50);color:var(--amber800)"',
ip:'10.0.50.10/24',
role:'Serveur applicatif hébergeant le site web public. Accessible uniquement depuis le Reverse Proxy — jamais directement depuis Internet.',
interfaces:['eth0 — DMZ (10.0.50.0/24)'],
protocols:'HTTP (interne), NTP, Syslog',
notes:'OS durci (CIS Benchmark). Ports ouverts : TCP 80 uniquement (depuis Rev.Proxy). Pas d\'accès SSH direct — via bastion.',
neighbors:['dmz_proxy'],
},
dmz_mail: {
title:'Mail Relay (DMZ)',
zone:'DMZ',
zoneCls:'style="background:var(--amber50);color:var(--amber800)"',
ip:'10.0.50.20/24',
role:'Relais de messagerie. Filtre le courrier entrant (spam, virus, phishing) avant livraison au serveur de messagerie interne.',
interfaces:['eth0 — DMZ (10.0.50.0/24)'],
protocols:'SMTP (TCP 25), STARTTLS, DKIM, SPF, DMARC, Antivirus',
notes:'Seul point d\'entrée email depuis Internet. Filtrage multi-couches. MX public pointe vers ce relay.',
neighbors:['dmz_proxy'],
},
core_a: {
title:'Core-SW-A (Commutateur cœur A)',
zone:'Cœur de réseau',
zoneCls:'style="background:var(--teal50);color:var(--teal800)"',
ip:'SVI VLAN 10 : 10.0.10.251/24 | SVI VLAN 20 : 10.0.20.254/24 | SVI VLAN 30 : 10.0.30.254/24',
role:'Commutateur de cœur Layer 3, moitié du cluster VSS. Routage inter-VLAN, liaison principale vers FW-01 et Dist-SW-1.',
interfaces:['Po1 — VSL vers Core-SW-B (2×40G LACP)','Po2 — vers FW-01 (trunk)','Po3 — vers Dist-SW-1 (LACP trunk)','Po4 — vers VPN-GW'],
protocols:'OSPF, HSRP/VRRP, STP (root), LACP, SNMP, LLDP, NetFlow',
notes:'Priorité STP root = 4096. HSRP priorité 110 sur tous les VLANs. Routes OSPF vers firewall.',
neighbors:['fw01','core_b','srv_sw','vpn_gw','dist1'],
},
core_b: {
title:'Core-SW-B (Commutateur cœur B)',
zone:'Cœur de réseau',
zoneCls:'style="background:var(--teal50);color:var(--teal800)"',
ip:'SVI VLAN 10 : 10.0.10.252/24 | SVI VLAN 20 : 10.0.20.253/24 | SVI VLAN 30 : 10.0.30.253/24',
role:'Commutateur de cœur Layer 3, moitié secondaire du cluster VSS. Redondant avec Core-SW-A.',
interfaces:['Po1 — VSL vers Core-SW-A (2×40G LACP)','Po5 — vers FW-02 (backup)','Po6 — vers Dist-SW-2 (LACP trunk)'],
protocols:'OSPF, HSRP/VRRP, STP, LACP, SNMP, NetFlow',
notes:'Priorité STP secondary root = 8192. HSRP priorité 100. Reprend automatiquement si Core-SW-A défaille.',
neighbors:['core_a','srv_sw','fw02','dist2'],
},
srv_sw: {
title:'Srv-Switch (Commutateur serveurs)',
zone:'Cœur de réseau',
zoneCls:'style="background:var(--teal50);color:var(--teal800)"',
ip:'SVI Mgmt : 10.0.10.3/24',
role:'Commutateur dédié aux serveurs internes. Ports en mode accès par VLAN, jumbo frames activés (MTU 9000) pour le trafic stockage/sauvegarde.',
interfaces:['Po10 — vers Core-SW-B (10G LACP)','Fa0/1-8 — serveurs (VLAN 40)','Fa0/9-12 — stockage/sauvegarde'],
protocols:'802.1Q, LACP, SNMP, Jumbo Frames (MTU 9000)',
notes:'Aucun accès utilisateur. Ports non utilisés désactivés (shutdown). VLAN 40 dédié.',
neighbors:['core_b','ad_dc','infra_srv','siem','file_db','backup'],
},
dist1: {
title:'Dist-SW-1 — Distribution Bâtiment A',
zone:'Distribution',
zoneCls:'style="background:var(--green50);color:var(--green600)"',
ip:'SVI Mgmt : 10.0.10.11/24',
role:'Commutateur de distribution du Bâtiment A. Agrège les commutateurs d\'accès, applique les politiques QoS VoIP.',
interfaces:['Po1 — uplink vers Core-SW-A (LACP trunk)','Gi1 — vers Acc-SW-1.1','Gi2 — vers Acc-SW-1.2'],
protocols:'STP/RSTP, LACP, 802.1Q, QoS, SNMP, DHCP relay',
notes:'DHCP relay vers serveur infra. QoS trust DSCP sur ports uplink, reclassification sur ports accès.',
neighbors:['core_a','acc11','acc12'],
},
dist2: {
title:'Dist-SW-2 — Distribution Bâtiment B',
zone:'Distribution',
zoneCls:'style="background:var(--green50);color:var(--green600)"',
ip:'SVI Mgmt : 10.0.10.12/24',
role:'Commutateur de distribution du Bâtiment B. Gère les VLANs utilisateurs et VoIP, connecte les APs WiFi.',
interfaces:['Po1 — uplink vers Core-SW-B (LACP trunk)','Gi1 — vers Acc-SW-2.1','Gi2 — vers Acc-SW-2.2','Gi3 — vers WAP (trunk V20,60)'],
protocols:'STP/RSTP, LACP, 802.1Q, QoS, SNMP, DHCP relay',
notes:'Uplink LACP vers Core-SW-B. Ports VoIP avec QoS DSCP EF automatique.',
neighbors:['core_b','acc21','acc22','wap'],
},
acc11: {
title:'Acc-SW-1.1 — Accès Bât.A Rdc',
zone:'Accès',
zoneCls:'style="background:var(--green50);color:var(--green600)"',
ip:'SVI Mgmt : 10.0.10.21/24',
role:'Commutateur d\'accès rez-de-chaussée du Bâtiment A. Ports utilisateurs en VLAN 20, ports VoIP en VLAN 30 (voice VLAN).',
interfaces:['Gi0/1 — uplink vers Dist-SW-1','Fa0/1-24 — postes (VLAN 20) + VoIP (voice VLAN 30)'],
protocols:'802.1Q, STP, PortFast, BPDU Guard, 802.1X (NAC), SNMP',
notes:'PortFast + BPDU Guard sur tous les ports utilisateurs. 802.1X avec RADIUS pour authentification des postes.',
neighbors:['dist1','users_a'],
},
acc12: {
title:'Acc-SW-1.2 — Accès Bât.A R1',
zone:'Accès',
zoneCls:'style="background:var(--green50);color:var(--green600)"',
ip:'SVI Mgmt : 10.0.10.22/24',
role:'Commutateur d\'accès 1er étage Bâtiment A. Configuration identique à Acc-SW-1.1.',
interfaces:['Gi0/1 — uplink vers Dist-SW-1','Fa0/1-24 — postes VLAN 20'],
protocols:'802.1Q, STP, PortFast, BPDU Guard, 802.1X, SNMP',
notes:'Redondance de lien non requise au niveau accès. Supervision SNMP depuis SIEM.',
neighbors:['dist1','users_a'],
},
acc21: {
title:'Acc-SW-2.1 — Accès Bât.B Rdc',
zone:'Accès',
zoneCls:'style="background:var(--green50);color:var(--green600)"',
ip:'SVI Mgmt : 10.0.10.23/24',
role:'Commutateur d\'accès rez-de-chaussée du Bâtiment B. Dédié VoIP (VLAN 30) et utilisateurs (VLAN 20).',
interfaces:['Gi0/1 — uplink vers Dist-SW-2','Fa0/1-12 — VoIP (VLAN 30)','Fa0/13-24 — postes (VLAN 20)'],
protocols:'802.1Q, Voice VLAN, STP, PortFast, 802.1X, SNMP',
notes:'Voice VLAN 30 configuré sur tous les ports. CDP utilisé pour auto-provision des phones Cisco.',
neighbors:['dist2','voip'],
},
acc22: {
title:'Acc-SW-2.2 — Accès Bât.B R1',
zone:'Accès',
zoneCls:'style="background:var(--green50);color:var(--green600)"',
ip:'SVI Mgmt : 10.0.10.24/24',
role:'Commutateur d\'accès 1er étage Bâtiment B. Utilisateurs et imprimantes réseau.',
interfaces:['Gi0/1 — uplink vers Dist-SW-2','Fa0/1-20 — postes VLAN 20','Fa0/21-24 — imprimantes VLAN 20'],
protocols:'802.1Q, STP, PortFast, 802.1X, SNMP',
notes:'Ports imprimantes : DHCP statique ou réservation MAC. Accès limité aux services d\'impression.',
neighbors:['dist2','printers'],
},
wap: {
title:'WiFi Access Points (×6)',
zone:'Accès',
zoneCls:'style="background:var(--green50);color:var(--green600)"',
ip:'Mgmt : 10.0.10.30-35/24 (un par AP)',
role:'Points d\'accès WiFi 802.11ax (Wi-Fi 6). Gérés centralement par un contrôleur WiFi. Diffusion de 2 SSIDs.',
interfaces:['Gi0 — trunk VLAN 20 (Corp) + VLAN 60 (Guests) vers Dist-SW'],
protocols:'802.11ax (Wi-Fi 6), WPA3-Enterprise (SSID Corp), Portail captif (SSID Guests), CAPWAP, RADIUS',
notes:'SSID Entreprise : WPA3 + 802.1X → VLAN 20. SSID Invités : portail captif → VLAN 60 (Internet uniquement). Contrôleur WiFi centralisé.',
neighbors:['dist2','guests'],
},
users_a: {
title:'Postes Bâtiment A',
zone:'Utilisateurs',
zoneCls:'style="background:var(--bg2);color:var(--muted)"',
ip:'10.0.20.x/24 (VLAN 20 — DHCP)',
role:'Postes de travail des collaborateurs. Windows 10/11, joints au domaine AD, gérés par GPO.',
interfaces:['NIC Ethernet (1 Gbps)'],
protocols:'DHCP, DNS, Kerberos, SMB/CIFS, RDP, HTTPS (via proxy)',
notes:'Authentification AD + MFA. EDR déployé. Accès web via proxy (WPAD). WSUS pour les mises à jour. 802.1X pour l\'accès réseau.',
neighbors:['acc11','acc12'],
},
voip: {
title:'Téléphones IP (VoIP)',
zone:'Utilisateurs',
zoneCls:'style="background:var(--bg2);color:var(--muted)"',
ip:'10.0.30.x/24 (VLAN 30 — DHCP option 66)',
role:'Téléphones IP sur VLAN dédié avec QoS. Provisioning automatique via TFTP/DHCP option 66.',
interfaces:['Ethernet 100 Mbps (pass-through pour PC)'],
protocols:'SIP, RTP/SRTP, TFTP, DHCP option 66, DSCP EF (46)',
notes:'Voice VLAN 30 totalement isolé du VLAN données. QoS DSCP EF priorisé sur toute la chaîne de commutation. Chiffrement SRTP recommandé.',
neighbors:['acc21'],
},
printers: {
title:'Imprimantes réseau',
zone:'Utilisateurs',
zoneCls:'style="background:var(--bg2);color:var(--muted)"',
ip:'10.0.20.x/24 (réservations DHCP par MAC)',
role:'Imprimantes réseau multi-fonctions. Adresses IP fixes via réservations DHCP.',
interfaces:['NIC Ethernet 100 Mbps'],
protocols:'LPR/LPD, IPP, SMB, SNMP, HTTP (interface admin)',
notes:'Accès limité aux sous-réseaux utilisateurs. Interface d\'administration désactivée ou restreinte par IP. Firmware à jour.',
neighbors:['acc22'],
},
guests: {
title:'Invités WiFi',
zone:'Utilisateurs',
zoneCls:'style="background:var(--bg2);color:var(--muted)"',
ip:'192.168.60.x/24 (VLAN 60 — DHCP isolé)',
role:'Réseau WiFi invités totalement isolé du LAN entreprise. Accès Internet uniquement via portail captif.',
interfaces:['WiFi 802.11ax'],
protocols:'DHCP, DNS (résolveur local), HTTP/S (Internet uniquement)',
notes:'VLAN 60 isolé — aucun accès aux ressources internes. Portail captif avec authentification code SMS ou voucher. Bande passante limitée (QoS).',
neighbors:['wap'],
},
ad_dc: {
title:'AD / Contrôleurs de Domaine (×2)',
zone:'Zone Serveurs',
zoneCls:'style="background:var(--purple50);color:var(--purple800)"',
ip:'DC1 : 10.0.40.10/24 | DC2 : 10.0.40.11/24',
role:'Contrôleurs de domaine Active Directory. Authentification Kerberos, GPO, réplication AD, DNS interne.',
interfaces:['NIC 1 Gbps (teaming actif/passif)'],
protocols:'LDAP (389), LDAPS (636), Kerberos (88), DNS (53), RPC, SYSVOL/NETLOGON, SNMP',
notes:'Deux DC en réplication complète (AD multi-master). Tier-0 : accès admin ultra-restreint. Sauvegarde quotidienne + snapshot horaire.',
neighbors:['srv_sw'],
},
infra_srv: {
title:'DNS · DHCP · NTP',
zone:'Zone Serveurs',
zoneCls:'style="background:var(--purple50);color:var(--purple800)"',
ip:'DNS1 : 10.0.40.20 | DHCP : 10.0.40.21 | NTP : 10.0.40.22',
role:'Serveurs d\'infrastructure réseau. DNS interne avec split-horizon, DHCP avec failover pair, NTP stratum 2.',
interfaces:['NIC 1 Gbps'],
protocols:'DNS UDP/TCP 53, DHCP UDP 67/68, NTP UDP 123, SNMP',
notes:'DNS: zones internes + forwarders vers 8.8.8.8 pour Internet. DHCP: failover pair RFC 3074. NTP: synchronisé sur sources publiques (stratum 1).',
neighbors:['srv_sw'],
},
siem: {
title:'SIEM / Syslog / Supervision',
zone:'Zone Serveurs',
zoneCls:'style="background:var(--purple50);color:var(--purple800)"',
ip:'10.0.40.30/24',
role:'SIEM (Security Information and Event Management). Collecte centralisée des logs de tous les équipements. Corrélation et alertes temps réel.',
interfaces:['NIC 10 Gbps (volume important de logs)'],
protocols:'Syslog UDP/TCP 514, NetFlow, SNMP Trap (162), API REST, TLS',
notes:'Collecte : FW, IPS, switches, serveurs, APs. Rétention 1 an. Alertes SOC 24/7. Tableau de bord sécurité. Intégration SOAR.',
neighbors:['srv_sw'],
},
file_db: {
title:'Serveurs Fichiers / Bases de données',
zone:'Zone Serveurs',
zoneCls:'style="background:var(--purple50);color:var(--purple800)"',
ip:'FS : 10.0.40.40/24 | DB : 10.0.40.41/24',
role:'Serveurs de fichiers (SMB/NFS) et bases de données métier. Données chiffrées au repos.',
interfaces:['NIC 10 Gbps (teaming, iSCSI séparé)'],
protocols:'SMB (445), NFS, SQL (1433/5432), iSCSI (3260), Backup agent',
notes:'ACL fines par groupe AD. Chiffrement BitLocker/dm-crypt. Snapshots toutes les heures. Journalisation des accès aux fichiers.',
neighbors:['srv_sw'],
},
backup: {
title:'Serveur de sauvegarde',
zone:'Zone Serveurs',
zoneCls:'style="background:var(--purple50);color:var(--purple800)"',
ip:'10.0.40.50/24',
role:'Solution de sauvegarde centralisée. Backup de tous les serveurs, VMs et postes critiques. Copie hors site chiffrée.',
interfaces:['NIC 10 Gbps'],
protocols:'Veeam/Commvault agent, iSCSI, S3 (cloud copy), TLS',
notes:'RTO < 4h, RPO < 24h. Règle 3-2-1 : 3 copies, 2 supports, 1 hors site. Test de restauration mensuel. Backup chiffré AES-256.',
neighbors:['srv_sw'],
},
};
// ─── Rendering ───────────────────────────────────────────────────────────────
const svg = document.getElementById('main-svg');
const NS = 'http://www.w3.org/2000/svg';
function el(tag, attrs={}, text='') {
const e = document.createElementNS(NS, tag);
for(const [k,v] of Object.entries(attrs)) e.setAttribute(k, v);
if(text) e.textContent = text;
return e;
}
// Zones
function renderZones() {
ZONES.forEach(z => {
const g = el('g');
const r = el('rect', { x:z.x, y:z.y, width:z.w, height:z.h,
fill:z.color, 'fill-opacity':'0.07', rx:'0' });
const border = el('rect', { x:z.x+0.5, y:z.y+0.5, width:z.w-1, height:z.h-1,
fill:'none', stroke:z.color, 'stroke-opacity':'0.2', 'stroke-width':'1' });
const txt = el('text', { x:z.labelX, y:z.labelY+10, fill:z.color,
'font-size':'9', 'font-weight':'700', 'text-transform':'uppercase',
'letter-spacing':'.08em', 'fill-opacity':'0.55', 'pointer-events':'none' }, z.label);
g.append(r, border, txt);
svg.appendChild(g);
});
}
// Links
function renderLinks() {
const g = el('g', { id:'links-layer' });
LINKS.forEach((lk, i) => {
const a = DEVS[lk.a], b = DEVS[lk.b];
if(!a || !b) return;
const line = el('line', {
id:`lk-${i}`,
x1:a.x, y1:a.y, x2:b.x, y2:b.y,
class:`lk ${lk.cls}`,
'data-a':lk.a, 'data-b':lk.b
});
g.appendChild(line);
if(lk.label) {
const mx = (a.x+b.x)/2 + (lk.lox||0);
const my = (a.y+b.y)/2 + (lk.loy||0);
const txt = el('text', { x:mx, y:my, class:'lk-label' }, lk.label);
g.appendChild(txt);
}
});
svg.appendChild(g);
}
// Devices
const W=72, H=46;
function renderDevices() {
const g = el('g', { id:'devs-layer' });
for(const [id, d] of Object.entries(DEVS)) {
const dg = el('g', { id:'d-'+id, class:'dev', tabindex:'0' });
dg.addEventListener('click', () => selectDev(id));
dg.addEventListener('keydown', e => { if(e.key==='Enter') selectDev(id); });
const bg = el('rect', {
class:'dev-bg', x:d.x-W/2, y:d.y-H/2, width:W, height:H, rx:'7',
fill:d.fill||'#f5f5f5', stroke:d.stroke||'#ccc', 'stroke-width':'1.2'
});
const icon = el('text', {
class:'dev-icon', x:d.x, y:d.y-8,
'font-size':'15', 'text-anchor':'middle', 'dominant-baseline':'middle'
}, d.icon);
const name = el('text', {
class:'dev-name', x:d.x, y:d.y+8,
'text-anchor':'middle', fill:'#333', 'dominant-baseline':'middle',
'font-size':'8.5', 'font-weight':'600'
}, d.label);
const sub = el('text', {
class:'dev-sub', x:d.x, y:d.y+19,
'text-anchor':'middle', fill:'#888', 'dominant-baseline':'middle',
'font-size':'7.2'
}, d.sub||'');
dg.append(bg, icon, name, sub);
g.appendChild(dg);
}
svg.appendChild(g);
}
// Select device
let selId = null;
function selectDev(id) {
// deselect previous
if(selId) {
const prev = document.getElementById('d-'+selId);
if(prev) prev.classList.remove('sel');
// reset link highlights
document.querySelectorAll('.lk.hi').forEach(l => l.classList.remove('hi'));
}
selId = id;
const dg = document.getElementById('d-'+id);
if(dg) dg.classList.add('sel');
// highlight connected links
document.querySelectorAll(`.lk[data-a="${id}"], .lk[data-b="${id}"]`).forEach(l => {
l.style.strokeOpacity = '1';
l.style.strokeWidth = '2.5';
});
const info = DEV_INFO[id];
const d = DEVS[id];
if(!info || !d) return;
const nb = (info.neighbors||[]).map(n => {
const nd = DEVS[n];
return `<span class="nb-tag" onclick="selectDev('${n}')">${nd?nd.icon:''} ${nd?nd.label:n}</span>`;
}).join('');
const ifaceHtml = (info.interfaces||[]).map(i => `<div style="font-size:12px;font-family:monospace;padding:2px 0;color:var(--muted)">${i}</div>`).join('');
document.getElementById('info-panel').innerHTML = `
<div style="display:flex;align-items:center;gap:10px;margin-bottom:10px;flex-wrap:wrap">
<span style="font-size:22px">${d.icon}</span>
<span class="ip-title">${info.title}</span>
<span class="ip-zone" ${info.zoneCls}>${info.zone}</span>
</div>
<div class="ip-grid">
<div class="ip-block">
<div class="ip-block-title">Adresses IP</div>
<div class="ip-block-val" style="font-family:monospace;font-size:11px">${info.ip}</div>
</div>
<div class="ip-block">
<div class="ip-block-title">Rôle</div>
<div class="ip-block-val">${info.role}</div>
</div>
${info.interfaces ? `<div class="ip-block">
<div class="ip-block-title">Interfaces</div>
<div class="ip-block-val">${ifaceHtml}</div>
</div>` : ''}
<div class="ip-block">
<div class="ip-block-title">Protocoles</div>
<div class="ip-block-val" style="font-size:12px">${info.protocols}</div>
</div>
</div>
${info.notes ? `<div style="font-size:12px;color:var(--text3);padding:6px 10px;background:var(--bg2);border-radius:var(--rad);margin-top:6px">📝 ${info.notes}</div>` : ''}
${nb ? `<div style="margin-top:8px"><div class="ip-block-title" style="font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--text3);margin-bottom:5px">Connecté à</div><div class="ip-neighbors">${nb}</div></div>` : ''}
`;
// re-dim previous links then highlight new
document.querySelectorAll('.lk').forEach(l => {
l.style.strokeOpacity = '';
l.style.strokeWidth = '';
});
document.querySelectorAll(`.lk[data-a="${id}"], .lk[data-b="${id}"]`).forEach(l => {
l.style.strokeOpacity = '1';
l.style.strokeWidth = '2.8';
});
}
// Legend
function renderLegend() {
const items = [
{ cls:'lk-wan', color:'#185FA5', dash:false, label:'Lien WAN / Internet' },
{ cls:'lk-main', color:'#0F6E56', dash:false, label:'Lien principal (data)' },
{ cls:'lk-vsl', color:'#185FA5', dash:false, label:'VSL / LACP haute capacité', width:3 },
{ cls:'lk-lacp', color:'#0F6E56', dash:false, label:'LACP Trunk (distribution)', width:2 },
{ cls:'lk-dmz', color:'#854F0B', dash:false, label:'Lien DMZ' },
{ cls:'lk-vpn', color:'#534AB7', dash:true, label:'Tunnel VPN' },
{ cls:'lk-ha', color:'#993C1D', dash:true, label:'Lien HA / Sync' },
{ cls:'lk-mgmt', color:'#9b9b94', dash:true, label:'Gestion / Supervision' },
{ cls:'lk-wifi', color:'#3B6D11', dash:true, label:'WiFi / Sans-fil' },
{ cls:'lk-backup',color:'#9b9b94', dash:true, label:'Sauvegarde / Backup (faible priorité)', width:1.5 },
];
const div = document.getElementById('legend');
items.forEach(item => {
const span = document.createElement('div');
span.className = 'leg-item';
const borderStyle = item.dash ? '2px dashed '+item.color : `${item.width||2}px solid ${item.color}`;
span.innerHTML = `<div class="leg-line" style="border-top:${borderStyle}"></div><span>${item.label}</span>`;
div.appendChild(span);
});
}
// Init
renderZones();
renderLinks();
renderDevices();
renderLegend();
</script>
</body>
</html>