Un lan pour une LAN, comment faire compliqué pour que ce soit simple!

Hello à tous,

Aujourd’hui petit retex sur un événement qui m’a fait extrêmement plaisir à participer, la GG-LAN #17 au Relecq-Kerhuon.

Nous nous éloignons des sujets audiovisuels pour rester dans l’événementiel.

Cet événement visait 24 équipes de 5 joueurs sur CS2, 32 joueurs sur Hearthstone Battleground en plus de 24 places de joueurs Free-Play, sur 2 jours, du 25 à 26 ocotobre 2025.

La préparation

Le Hardware

Pour couvrir un événement de ce genre, il nous faut convenir :

  • d’un plan de table, avec l’organisation des salles de jeu pour permettre la répartition électrique et réseau
  • d’une connexion Internet nominale, capable d’encaisser le débit souhaité
  • d’une solution d’accès à Internet de secours, si possible en pouvant gérer une bascule la plus transparente possible de l’une à l’autre

Une fois ces problématiques bien repérées nous avons commencé à travailler.

D’abord, le plan d’implantation, où ont été prévus le placement des switchs réseaux pour l’accès en ethernet, des bornes Wi-Fi, ainsi que les éléments centraux, coeur de réseau, distribution…

Dans l’idée, tout a été réalisé en point à point, limitant un maxime le chaînage des équipements réseaux.

Pour gérer les distances, des ensembles de fibres ont été prévus ; moins encombrant, plus simple à installer puis à ranger, plus simple à dépanner, quand l’on est averti, la fibre c’est magique !

Un mix de fibre de 50m OS2 monomode renforcée ont été utilisées, détournées de leur usage initial servant pour déplacer des box Internet loin des PTO.

De plus, un mix de transport via des cassettes MPO et breakout ont aussi été utilisés, pour limiter le nombre de longueurs de 50m, et permettre un démontage plus rapide.

L’infrastructure

côté software, il a fallu déployer quelques logiciels pour que le réseau fonctionne :

  • Un DHCP, pour assigner les IPv4 et les DNS aux différents sous-réseaux,
  • Un DNS, pour donner des adresses IPv4 en fonction du serveur de nom, ou rediriger vers le LANCache,
  • Un LANCache, pour accélérer les téléchargements des jeux,
  • Un LibreNMS, pour monitorer chacun des équipements réseaux en ligne

Tout cela a été déployé sur un minisforum, un serveur compact équipé de 2xSFP+ 10GbE qui fait tourner l’hyperviseur proxmox.

Le coeur de réseau

Le coeur - Arista 7280SR

Le switch L3 central du coeur de réseau porte tout le LAN et le L3 en VRF. Cela permet d’avoir un réseau uniforme centralisé, non dépendant de la redondance des pare-feux.

core01-lan#show run
! Command: show running-config
! device: core01-lan (DCS-7280SR-48C6, EOS-4.33.5M)
!
errdisable recovery cause bpduguard
errdisable recovery cause hitless-reload-down
errdisable recovery cause lacp-rate-limit
errdisable recovery cause link-flap
errdisable recovery cause no-internal-vlan
errdisable recovery cause portchannelguard
errdisable recovery cause portsec
errdisable recovery cause speed-misconfigured
errdisable recovery cause uplink-failure-detection
errdisable recovery cause xcvr-overheat
errdisable recovery cause xcvr-unsupported
errdisable recovery interval 30
!
no service interface inactive port-id allocation disabled
!
transceiver qsfp default-mode 4x10G
!
service routing protocols model multi-agent
!
hostname core01-lan
ip name-server vrf default 1.1.1.1
!
snmp-server community akwa ro
snmp-server community public ro
snmp-server community qgK3hB8sePXOMI5 ro
snmp-server vrf VRF-LAN
!
spanning-tree mode mstp
spanning-tree root super
!
service unsupported-transceiver wiprolabs f5047577
!
system l1
   unsupported speed action error
   unsupported error-correction action error
!
environment fan-speed override 30
!
vlan 42
   name SVC_User
!
vlan 97
   name LAN_Admin
!
vlan 98
   name SVC_Internes
!
vlan 99
   name SVC_Network
!
vlan 100
   name NEWCS2
!
vlan 101
   name LAN_CS2
!
vlan 102
   name LAN_Hearthstone
!
vlan 103
   name LAN_Smash
!
vlan 104
   name LAN_Public
!
vlan 105
   name LAN_Caster
!
vlan 274
   name temp_interco
!
vlan 999
!
vlan 1000
   name WAN_Relecq
!
vlan 1001
   name wan_viastarlink
!
vrf instance VRF-LAN
!
interface Port-Channel125
   switchport trunk allowed vlan 99-105
   switchport mode trunk
!
interface Port-Channel127
   description Po: hvcore
   switchport mode trunk
!
interface Ethernet1
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet2
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet3
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet4
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet5
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet6
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet7
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet8
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet9
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet10
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet11
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet12
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet13
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet14
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet15
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet16
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet17
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet18
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet19
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet20
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet21
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet22
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet23
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet24
   switchport trunk allowed vlan 97,99-105
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet25
   description Core: CCR WAN
   switchport access vlan 1000
   ip address 45.112.120.70/31
   ipv6 address 2a06:c484:1666:0:b00b::/127
!
interface Ethernet26
   description Core: CCR LAN
   no switchport
   vrf VRF-LAN
   ip address 45.112.120.73/31
   ipv6 address 2a06:c484:1666:0:b00b::3/127
!
interface Ethernet27
   description Core: hvcore
   no switchport
   ip address 192.168.0.1/24
   dhcp server ipv4
   ipv6 address 2a06:c480:1::/64
   channel-group 127 mode active
!
interface Ethernet28
   description Core: hvcore
   channel-group 127 mode active
!
interface Ethernet29
   shutdown
   switchport access vlan 1000
!
interface Ethernet30
   switchport trunk allowed vlan 999
   switchport mode trunk
   switchport vlan translation 1421 999
   spanning-tree bpdufilter enable
!
interface Ethernet31
   description Core: CPE Wild
   no switchport
!
interface Ethernet31.99
   encapsulation dot1q vlan 99
   vlan id 99
!
interface Ethernet31.1422
   encapsulation dot1q vlan 1422
   vlan id 1001
!
interface Ethernet32
!
interface Ethernet33
   description Switch: Entree
   switchport mode trunk
!
interface Ethernet34
!
interface Ethernet35
   description Core: Satellite
   channel-group 125 mode active
!
interface Ethernet36
!
interface Ethernet37
   description Core: SW Mgmt
   switchport access vlan 99
!
interface Ethernet38
!
interface Ethernet39
!
interface Ethernet40
!
interface Ethernet41
!
interface Ethernet42
!
interface Ethernet43
!
interface Ethernet44
!
interface Ethernet45
!
interface Ethernet46
!
interface Ethernet47
   description Uplink: Local WAN
   no switchport
   ip address 45.112.120.127/31
!
interface Ethernet48
   description Core: SW Uplink
   switchport trunk allowed vlan 99,1000
   switchport mode trunk
!
interface Ethernet49/1
!
interface Ethernet50/1
!
interface Ethernet51/1
!
interface Ethernet52/1
!
interface Ethernet53/1
!
interface Ethernet54/1
!
interface Management1
   ip address 192.168.88.1/24
   ip address 10.99.0.4/24 secondary
!
interface Vlan42
   vrf VRF-LAN
   ip address 10.42.0.1/24
!
interface Vlan97
   vrf VRF-LAN
   ip address 10.97.0.1/24
   ip helper-address 10.42.0.67
!
interface Vlan98
   vrf VRF-LAN
   ip address 10.98.0.1/24
   ip helper-address 10.42.0.67
!
interface Vlan99
   vrf VRF-LAN
   ip address 10.99.0.1/24
   ip helper-address 10.42.0.67
!
interface Vlan100
   vrf VRF-LAN
   ip address 10.101.0.1/16
   ip helper-address 10.42.0.67
!
interface Vlan102
   vrf VRF-LAN
   ip address 45.112.121.1/24
   ip helper-address 10.42.0.67
!
interface Vlan103
   vrf VRF-LAN
   ip address 10.103.0.1/16
   ip helper-address 10.42.0.67
!
interface Vlan104
   vrf VRF-LAN
   ip address 10.104.0.1/16
   ip helper-address 10.42.0.67
!
interface Vlan105
   vrf VRF-LAN
   ip address 45.112.120.129/26
   ip helper-address 10.42.0.67
!
interface Vlan274
   ip address 10.8.89.1/24
!
interface Vlan999
   ip address 45.112.120.65/31
   ipv6 address 2a06:c484:1666:0:cafe::1/127
!
interface Vlan1000
   description WAN: Relecq
   shutdown
   mtu 1500
   ip address 90.83.100.20/27
!
interface Vlan1001
   ip address 45.112.120.67/31
!
ip routing
ip routing vrf VRF-LAN
!
ip prefix-list PFX-DEDICATED-MORESPEC-V4
   seq 10 permit 45.112.120.64/26 le 32
   seq 20 permit 45.112.120.128/25 le 32
   seq 30 permit 45.112.121.0/24 le 32
!
ip prefix-list PFX-DEDICATED-V4
   seq 10 permit 45.112.120.64/26
   seq 20 permit 45.112.120.128/25
   seq 30 permit 45.112.121.0/24
!
ip prefix-list PFX-DEFAULT-V4
   seq 5 permit 0.0.0.0/0
!
ipv6 prefix-list PFX-DEDICATED-MORESPEC-V6
   seq 10 permit 2a06:c484:1666::/48 le 64
!
ipv6 prefix-list PFX-DEDICATED-V6
   seq 10 permit 2a06:c484:1666::/48
!
ipv6 prefix-list PFX-DEFAULT-V6
   seq 10 permit ::/0
!
ipv6 unicast-routing
ipv6 unicast-routing vrf VRF-LAN
!
ip route 31.7.252.53/32 90.83.100.1 name wan_relecq_jaguar
ip route 45.112.120.64/26 Null0 254
ip route 45.112.120.128/25 Null0 254
ip route 45.112.121.0/24 Null0 254
ip route 87.236.35.131/32 90.83.100.1 name wan_relecq
ip route 185.126.229.69/32 90.83.100.1 name wan_relecq_moji1
!
ipv6 route 2a06:c484:1666::/48 Null0 254
!
route-map RM-ACCEPT permit 10
!
route-map RM-ACCEPT-DEFAULT-V4 permit 10
   match ip address prefix-list PFX-DEFAULT-V4
!
route-map RM-ACCEPT-DEFAULT-V6 permit 10
   match ipv6 address prefix-list PFX-DEFAULT-V6
!
route-map RM-DEDICATED-MORESPEC-V4 permit 10
   match ip address prefix-list PFX-DEDICATED-MORESPEC-V4
!
route-map RM-DEDICATED-MORESPEC-V6 permit 10
   match ipv6 address prefix-list PFX-DEDICATED-MORESPEC-V6
!
route-map RM-DEDICATED-V4 permit 10
   match ip address prefix-list PFX-DEDICATED-V4
!
route-map RM-DEDICATED-V6 permit 10
   match ipv6 address prefix-list PFX-DEDICATED-V6
!
router bgp 4290000016
   router-id 45.112.121.0
   neighbor 45.112.120.64 remote-as 47160
   neighbor 45.112.120.64 update-source 45.112.120.65
   neighbor 45.112.120.64 ebgp-multihop 64
   neighbor 45.112.120.66 remote-as 47160
   neighbor 45.112.120.66 shutdown
   neighbor 45.112.120.66 update-source 45.112.120.67
   neighbor 45.112.120.66 ebgp-multihop
   neighbor 45.112.120.71 remote-as 65000
   neighbor 45.112.120.71 update-source 45.112.120.70
   neighbor 2a06:c484:1666:0:b00b::1 remote-as 65000
   neighbor 2a06:c484:1666:0:b00b::1 update-source 2a06:c484:1666:0:b00b::
   neighbor 2a06:c484:1666:0:cafe:: remote-as 47160
   neighbor 2a06:c484:1666:0:cafe:: update-source 2a06:c484:1666:0:cafe::1
   neighbor 2a06:c484:1666:0:cafe:: ebgp-multihop 64
   !
   address-family ipv4
      neighbor 45.112.120.64 activate
      neighbor 45.112.120.64 route-map RM-ACCEPT in
      neighbor 45.112.120.64 route-map RM-DEDICATED-V4 out
      neighbor 45.112.120.66 activate
      neighbor 45.112.120.66 route-map RM-ACCEPT in
      neighbor 45.112.120.66 route-map RM-DEDICATED-V4 out
      neighbor 45.112.120.71 activate
      neighbor 45.112.120.71 route-map RM-DEDICATED-MORESPEC-V4 in
      neighbor 45.112.120.71 route-map RM-ACCEPT-DEFAULT-V4 out
      redistribute connected
      redistribute static
   !
   address-family ipv6
      neighbor 2a06:c484:1666:0:b00b::1 activate
      neighbor 2a06:c484:1666:0:b00b::1 route-map RM-DEDICATED-MORESPEC-V6 in
      neighbor 2a06:c484:1666:0:b00b::1 route-map RM-ACCEPT-DEFAULT-V6 out
      neighbor 2a06:c484:1666:0:cafe:: activate
      neighbor 2a06:c484:1666:0:cafe:: route-map RM-ACCEPT in
      neighbor 2a06:c484:1666:0:cafe:: route-map RM-DEDICATED-V6 out
      redistribute connected
      redistribute static
   !
   vrf VRF-LAN
      neighbor 45.112.120.72 remote-as 65000
      neighbor 45.112.120.72 local-as 65001 no-prepend replace-as
      neighbor 45.112.120.72 update-source 45.112.120.73
      neighbor 2a06:c484:1666:0:b00b::2 remote-as 65000
      neighbor 2a06:c484:1666:0:b00b::2 local-as 65001 no-prepend replace-as
      neighbor 2a06:c484:1666:0:b00b::2 update-source 2a06:c484:1666:0:b00b::3
      !
      address-family ipv4
         neighbor 45.112.120.72 activate
         neighbor 45.112.120.72 route-map RM-ACCEPT in
         neighbor 45.112.120.72 route-map RM-ACCEPT out
         redistribute connected
         redistribute static
      !
      address-family ipv6
         neighbor 2a06:c484:1666:0:b00b::2 activate
         neighbor 2a06:c484:1666:0:b00b::2 route-map RM-ACCEPT in
         neighbor 2a06:c484:1666:0:b00b::2 route-map RM-ACCEPT out
         redistribute connected
         redistribute static
!
router multicast
   ipv4
      software-forwarding kernel
   !
   ipv6
      software-forwarding kernel
!
management ssh
   vrf VRF-LAN
   !
   vrf default
!
end

Le Satellite - Arista 7050SX

Le satellite est utilisé en simple switch L2 qui commute les vlans entre les ports. Cependant, ils ont été privilégiés car les switchs arista, le coeur et le satellite, s’imposent spanning-tree super root, de ce fait une boucle L2 ne peut pas se propager à travers le reste du réseau.

satellite01-lan#show run
! Command: show running-config
! device: satellite01-lan (DCS-7050SX-64, EOS-4.28.13.1M)
!
transceiver qsfp default-mode 4x10G
!
service routing protocols model multi-agent
!
hostname satellite01-lan
ip name-server vrf default 1.1.1.1
!
snmp-server community public ro
snmp-server community qgK3hB8sePXOMI5 ro
!
spanning-tree mode mstp
spanning-tree root super
!
service unsupported-transceiver wiprolabs f5047577
!
environment fan-speed override 30
!
vlan 97,100-105
!
vlan 99
   name SVC_Network
!
interface Port-Channel147
   switchport mode trunk
   spanning-tree bpdufilter enable
!
interface Ethernet1
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet2
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet3
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet4
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet5
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet6
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet7
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet8
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet9
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet10
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet11
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet12
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet13
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet14
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet15
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet16
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet17
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet18
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet19
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet20
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet21
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet22
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet23
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet24
   switchport mode trunk
   storm-control broadcast level 0.01
   storm-control multicast level 0.01
   storm-control unknown-unicast level 0.01
!
interface Ethernet25
   switchport mode trunk
!
interface Ethernet26
   switchport mode trunk
!
interface Ethernet27
   switchport mode trunk
!
interface Ethernet28
   switchport mode trunk
!
interface Ethernet29
   switchport mode trunk
!
interface Ethernet30
   switchport mode trunk
!
interface Ethernet31
   switchport mode trunk
!
interface Ethernet32
   switchport mode trunk
!
interface Ethernet33
   switchport mode trunk
!
interface Ethernet34
   switchport mode trunk
!
interface Ethernet35
   switchport mode trunk
!
interface Ethernet36
   switchport mode trunk
!
interface Ethernet37
   switchport mode trunk
!
interface Ethernet38
   switchport mode trunk
!
interface Ethernet39
   switchport mode trunk
!
interface Ethernet40
   switchport mode trunk
!
interface Ethernet41
   switchport mode trunk
!
interface Ethernet42
   switchport mode trunk
!
interface Ethernet43
   switchport mode trunk
!
interface Ethernet44
   switchport mode trunk
!
interface Ethernet45
   switchport mode trunk
!
interface Ethernet46
   switchport mode trunk
!
interface Ethernet47
   switchport mode trunk
   channel-group 147 mode active
!
interface Ethernet48
   switchport mode trunk
   channel-group 147 mode active
!
interface Ethernet49/1
!
interface Ethernet49/2
!
interface Ethernet49/3
!
interface Ethernet49/4
!
interface Ethernet50/1
!
interface Ethernet50/2
!
interface Ethernet50/3
!
interface Ethernet50/4
!
interface Ethernet51/1
!
interface Ethernet51/2
!
interface Ethernet51/3
!
interface Ethernet51/4
!
interface Ethernet52/1
!
interface Ethernet52/2
!
interface Ethernet52/3
!
interface Ethernet52/4
!
interface Management1
   ip address 192.168.88.1/24
!
interface Vlan99
   ip address 10.99.0.2/24
!
ip routing
!
ip route 0.0.0.0/0 10.99.0.1
!
end

Les switchs de distribution

Côté MikroTik, la configuration est répartie entre les CSS326 qui ne peuvent se configurer qu’à travers l’interface web, et les CRS326 qui tournent sous RouterOS qui se configurent via Winbox / CLI.

[admin@lan-r2] > export
# 2025-10-26 18:04:56 by RouterOS 7.20.2
# software id = W0RW-MLJU
#
# model = CRS326-24G-2S+
# serial number = 94550A08B6A1
/interface bridge
add admin-mac=74:4D:28:47:7C:40 auto-mac=no comment=defconf name=bridge port-cost-mode=short protocol-mode=mstp \
    vlan-filtering=yes
/interface vlan
add interface=bridge name=vlan99 vlan-id=99
/interface lte apn
set [ find default=yes ] ip-type=ipv4 use-network-apn=no
/interface wireless security-profiles
set [ find default=yes ] supplicant-identity=MikroTik
/port
set 0 name=serial0
/snmp community
set [ find default=yes ] name=qgK3hB8sePXOMI5
/interface bridge port
add bridge=bridge comment=defconf ingress-filtering=no interface=ether1 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether2 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether3 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether4 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether5 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether6 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether7 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether8 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether9 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether10 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether11 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether12 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether13 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether14 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether15 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether16 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether17 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether18 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether19 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether20 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether21 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether22 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether23 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=ether24 internal-path-cost=10 path-cost=10 pvid=100
add bridge=bridge comment=defconf ingress-filtering=no interface=sfp-sfpplus1 internal-path-cost=10 path-cost=10
add bridge=bridge comment=defconf ingress-filtering=no interface=sfp-sfpplus2 internal-path-cost=10 path-cost=10
/ip firewall connection tracking
set udp-timeout=10s
/ip neighbor discovery-settings
set discover-interface-list=!dynamic
/ip settings
set max-neighbor-entries=8192
/interface bridge vlan
add bridge=bridge tagged=bridge,sfp-sfpplus2 vlan-ids=99
add bridge=bridge tagged=sfp-sfpplus2 vlan-ids=100
/interface ovpn-server server
add auth=sha1,md5 mac-address=FE:55:7E:FD:EA:87 name=ovpn-server1
/ip address
add address=192.168.88.1/24 comment=defconf interface=bridge network=192.168.88.0
add address=10.99.0.52/24 interface=vlan99 network=10.99.0.0
/ip dns
set servers=1.1.1.1
/ip hotspot profile
set [ find default=yes ] html-directory=hotspot
/ip ipsec profile
set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5
/ip route
add disabled=no dst-address=0.0.0.0/0 gateway=10.99.0.1
/routing bfd configuration
add disabled=no interfaces=all min-rx=200ms min-tx=200ms multiplier=5
/snmp
set enabled=yes
/system clock
set time-zone-name=Europe/Paris
/system identity
set name=lan-r2

Le DHCP - Le DNS - Le LANCache

Pour un bon fonctionnement du LANCache, tout un ensemble DHCP/DNS/LANCache doivent être accordés pour aiguiller le trafic utilisateur correctement vers le serveur de cache et non les ressources disponibles sur Internet.

Le DHCP

Pour le DHCP, un simple serveur Kea + Stork pour nous afficher les états de remplissage des réseaux en nombre d’adresse que nous avons prévu d’assigner :

Le DHCP travaille en tandem avec le routeur de coeur, qui en réalité transfert les demandes de DHCP au serveur.

Le DNS

Les DNS ont été légèrement bricolés. En effet, initialement il fallait de l’IPv6. Finalement, ne l’avons pas activé car le réseau fournit n’en disposait pas, et le RBCI, réseau d’Orange Business, ne permet pas l’établissement de tunnels stables.

De ce fait, un DNS en Python a été rapidement écrit à l’aide ChatGPT :

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# DNS proxy pour LANcache :
# 1) Interroge d'abord le résolveur LANcache.
#    - Si un enregistrement A == 10.42.0.42 -> renvoie la réponse LANcache telle quelle (et AAAA -> NOERROR/NODATA).
# 2) Sinon, interroge des résolveurs publics (IPv4 et/ou IPv6) et renvoie leur réponse telle quelle.
#
# Dépendances : pip install dnslib
#
import socket
import threading
from dnslib import DNSRecord, DNSHeader, DNSLabel, DNSQuestion, QTYPE, RCODE, A, RR

# ========= CONFIG =========
# Écoute IPv4 et IPv6 (deux sockets)
LISTEN_ADDR_V4 = "0.0.0.0"
LISTEN_ADDR_V6 = "::"
LISTEN_PORT = 5353

# Résolveur LANcache (là où les rewrites ont lieu)
LANCACHE_RESOLVER = ("10.42.0.42", 53)   # ← change ici (IP:port de lancache-dns)

# IP de hit LANcache attendue
LANCACHE_HIT_IP = "10.42.0.42"              # ← change ici

# Résolveurs publics de fallback (IPv6 et/ou IPv4)
EXTERNAL_RESOLVERS = [
#    ("2606:4700:4700::1111", 53),  # Cloudflare v6
    ("1.1.1.1", 53),               # Cloudflare v4
#    ("2001:4860:4860::8888", 53),  # Google v6
    ("8.8.8.8", 53),               # Google v4
]

UPSTREAM_TIMEOUT = 1.5
RETRIES = 1
# ==========================


# ---------- Helpers réseau ----------
def _sock_for_ip(ip: str):
    if ":" in ip:
        s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
    else:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.settimeout(UPSTREAM_TIMEOUT)
    return s

def udp_query(pkt: bytes, upstream):
    ip, port = upstream
    for _ in range(RETRIES + 1):
        s = None
        try:
            s = _sock_for_ip(ip)
            s.sendto(pkt, (ip, port))
            data, _ = s.recvfrom(4096)
            s.close()
            return data
        except Exception:
            if s:
                try:
                    s.close()
                except Exception:
                    pass
    return None


# ---------- DNS utils ----------
def ask(upstream, q: DNSRecord):
    data = udp_query(q.pack(), upstream)
    try:
        return DNSRecord.parse(data) if data else None
    except Exception:
        return None

def has_lancache_hit_a(resp: DNSRecord) -> bool:
    if not resp or resp.header.rcode != RCODE.NOERROR:
        return False
    for rr in resp.rr:
        if rr.rtype == QTYPE.A and str(rr.rdata) == LANCACHE_HIT_IP:
            return True
    return False

def nodata_for(q: DNSRecord) -> DNSRecord:
    # NOERROR / NODATA: même ID et question, sans answer
    hdr = DNSHeader(id=q.header.id, qr=1, aa=0, ra=1, rd=q.header.rd, rcode=RCODE.NOERROR)
    return DNSRecord(hdr, q.q)

def filter_only_a_from(resp: DNSRecord) -> DNSRecord:
    # Garde uniquement les RRs de type A (optionnel si tu veux forcer le retour "A only")
    new = DNSRecord(
        DNSHeader(id=resp.header.id, qr=1, aa=resp.header.aa, ra=1, rd=resp.header.rd, rcode=resp.header.rcode),
        q=resp.q
    )
    for rr in resp.rr:
        if rr.rtype == QTYPE.A:
            new.add_answer(rr)
    return new

def forward_to_any_external(q: DNSRecord):
    for upstream in EXTERNAL_RESOLVERS:
        r = ask(upstream, q)
        if r is not None:
            return r
    return None


# ---------- Traitement d'une requête ----------
def handle_query(data: bytes, addr, sock):
    try:
        client_q = DNSRecord.parse(data)
    except Exception:
        return

    qname_str = str(client_q.q.qname)  # garde la forme « example.com. »
    qtype = client_q.q.qtype

    # 1) Interroger LANcache d'abord avec le même type
    resp_lc_same = ask(LANCACHE_RESOLVER, client_q)

    # --- Cas AAAA : on décide via un probe A @ LANcache ---
    if qtype == QTYPE.AAAA:
        name = DNSLabel(qname_str)
        probe_a = DNSRecord(DNSHeader(rd=1), q=DNSQuestion(name, QTYPE.A))
        a_from_lancache = ask(LANCACHE_RESOLVER, probe_a)

        if a_from_lancache and has_lancache_hit_a(a_from_lancache):
            # Hit LANcache → on supprime AAAA
            sock.sendto(nodata_for(client_q).pack(), addr)
            return
        else:
            # Pas de hit (ou timeout) → AAAA via résolveurs publics
            resp_ext = forward_to_any_external(client_q)
            if resp_ext is None:
                # Repli : si LANcache répondait quelque chose, renvoie-le, sinon SERVFAIL
                if resp_lc_same is not None:
                    sock.sendto(resp_lc_same.pack(), addr)
                else:
                    fail = client_q.reply(); fail.header.rcode = RCODE.SERVFAIL
                    sock.sendto(fail.pack(), addr)
                return
            sock.sendto(resp_ext.pack(), addr)
            return

    # --- Cas A : si hit, on renvoie la réponse LANcache telle quelle ---
    if qtype == QTYPE.A:
        if has_lancache_hit_a(resp_lc_same):
            # Tu peux choisir de ne renvoyer que les A (filter_only_a_from)
            # Ici, on renvoie la réponse LANcache telle quelle :
            sock.sendto(resp_lc_same.pack(), addr)
            return
        else:
            # Pas de hit → résolveurs publics
            resp_ext = forward_to_any_external(client_q)
            if resp_ext is None:
                # Repli : renvoyer LANcache si dispo, sinon SERVFAIL
                if resp_lc_same is not None:
                    sock.sendto(resp_lc_same.pack(), addr)
                else:
                    fail = client_q.reply(); fail.header.rcode = RCODE.SERVFAIL
                    sock.sendto(fail.pack(), addr)
                return
            sock.sendto(resp_ext.pack(), addr)
            return

    # --- Autres types (NS, MX, TXT, CNAME...) ---
    # On préfère la réponse publique; si échec, on renvoie celle de LANcache si on l'a.
    resp_ext = forward_to_any_external(client_q)
    if resp_ext is None:
        if resp_lc_same is not None:
            sock.sendto(resp_lc_same.pack(), addr)
        else:
            fail = client_q.reply(); fail.header.rcode = RCODE.SERVFAIL
            sock.sendto(fail.pack(), addr)
        return
    sock.sendto(resp_ext.pack(), addr)


# ---------- Serveurs UDP IPv4 & IPv6 ----------
def serve_on(sock):
    while True:
        data, addr = sock.recvfrom(4096)
        threading.Thread(target=handle_query, args=(data, addr, sock), daemon=True).start()

def serve():
    # IPv4
    s4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s4.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s4.bind((LISTEN_ADDR_V4, LISTEN_PORT))

    # IPv6
    s6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
    s6.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    # Laisse IPV6_V6ONLY=1 pour éviter les surprises, on a déjà un socket IPv4 séparé.
    s6.bind((LISTEN_ADDR_V6, LISTEN_PORT))

    print(f"[+] DNS proxy listening on {LISTEN_ADDR_V4}:{LISTEN_PORT} (IPv4)")
    print(f"[+] DNS proxy listening on [{LISTEN_ADDR_V6}]:{LISTEN_PORT} (IPv6)")

    threading.Thread(target=serve_on, args=(s4,), daemon=True).start()
    serve_on(s6)

if __name__ == "__main__":
    serve()

C’est un script tout bête, qui pour toute requête A ou AAAA réalisera une requête A sur le LANCache. Si ce dernier répond de son IP, c’est qu’il faut renvoyer le client en IPv4, donc donner la réponse en A du LANCache vers le client, ou retourner no-existent en AAAA pour encourage le client à réaliser son téléchargement en IPv4 vers le LANCache.

Si le LANCache ne retourne pas son adresse IPv4 dans la réponse A, ou qu’il ne répond plus à cause d’un quelconque crash, alors les résolveurs sont requêtés pour pouvoir répondre aux clients.

En face de ce script, un simple serveur Unbound a été déployé, dans le but de cacher les réponse du DNS en python et donc limiter sa charge et encaisser les possibles crash.

La configuration unbound était donc minimaliste :

server:
  # Listen for your LAN
  interface: 0.0.0.0
  interface: ::0
  access-control: 0.0.0.0/0 allow
  access-control: ::/0 allow

  do-ip4: yes
  do-ip6: no
  do-udp: yes
  do-tcp: yes
  do-not-query-localhost: no

  # Cache & resilience
  msg-cache-size: 128m
  rrset-cache-size: 256m
  cache-min-ttl: 30
  cache-max-ttl: 86400
  prefetch: yes

  # Serve stale answers when all upstreams fail
  serve-expired: yes
  serve-expired-ttl: 86400
  serve-expired-reply-ttl: 30
  # (Optional RFC8767 behavior: only after short wait)
  # serve-expired-client-timeout: 1800   # in ms (1.8s)

  # Upstream retry tuning (per nameserver)
  outbound-msg-retry: 5   # default 5; lower switches faster to next forwarder

  # PMTU-safe EDNS and some hardening
  edns-buffer-size: 1232
  qname-minimisation: yes
  harden-dnssec-stripped: yes

  local-data: "unifi. IN A 45.13.105.225"
  local-data: "ebot.lan. IN A 10.101.11.200"
  local-data: "ebot.gglan. IN A 10.42.0.24"
  local-data: "ebot. IN A 10.101.11.200"
  local-data: "librenms.lan. IN A 10.42.0.161"

# Always try the Python proxy first; if it times out/fails, Unbound uses the next ones.
forward-zone:
  name: "."
  forward-addr: 127.0.0.1@5353

Configuration minimaliste, mais qui nous a permis de définir quelques nom de domaine internes tels que les enregistrements permettant aux joueurs de rejoindre eBot, ou aux bornes Wi-Fi UniFi de rejoindre le contrôleur pour leur adoptation.

La supervision

Une supervision avec LibreNMS a été rapidement mise en place pour surveiller le trafic, et surtout le niveau optique de toutes les connexions fibres pour s’assurer que les atténuations soient dans des niveaux corrects.

En production !

Par rapport au projet initial, une déconvenue est survenue ; la connexion donnée de 800Mbps symétrique proposée sur une IPv4 publique en direct était bien fonctionnelle, cependant toute tentative de monter un tunnel GRE / L2TP / Wireguard a été vaine, avec des débits et comportement aléatoires.

De ce fait, il a été décidé de placer les 200 joueurs directement derrière l’unique adresse IPv4 disponible. Bourrin mais fonctionnel :zany_face:

Du réseau Wi-Fi a été déployé en plus, mais avec un usage en réalité limité, utilisé essentiellement par les admins et quelques joueurs.

Des joueurs contents, une LAN qui tourne. Le débit utile par joueur est de 200Mbps ce qui est convenable.

Côté réseau, ça a débité pas mal, une bonne moyenne pour une LAN de ce genre !

On constate énormément d’usage de la connexion en upload ; et c’est bien normal, aujourd’hui nous avons besoin de streamers pour couvrir l’événément !

Tournoi CS2

Le Free-Play et Hearthstone Battleground étant des jeux soit en ligne, soit locaux, peu de contraintes étaient vraiment présentes sur l’organisation technique à part un accès à Internet, et encore.

Cependant sur CS2, les admins de la GG-LAN ont charbonné pour faire tourner une stack de serveur de jeux CS2 via Pterodactyl et évidemment mis à disposition eBot, pour le suivi des tournois par les joueurs et leur administration pour les admins.

Conclusion ?

La conclusion, a été un événement qui a tourné comme une horloge.

Oui, nous avons eu des mauvaises surprises sur l’accès Internet public à cause de l’accès Orange au déploiement,

Oui, nous avons eu des surprises au début de la LAN, dont la MTU de 1500 par défaut des switchs FS ne prenaient pas en compte l’overhead vlan que nous avons mis sur les switchs, posant des problèmes de joignabilité dont eBot dans le même vlan joueur ou le LANcache,

Cependant, ces menus problèmes ont très vite été balayés! L’événement a été un succès, et on repart sûrement l’année prochaine, à l’espace Avel Vor !

Merci et GGWP à toute l’équipe GG-LAN qui réalise de superbes événements à chaque fois ! La recontre aura été formidable.