# Entorno 5G Core
## Descripción del entorno
Se encuentra en la máquina 192.168.159.75.
La arquitectura desplegada se asemeja a la siguinte
La topología desplegada es la siguiente

## Confifuración del entorno
A excepción del ```dockerfile``` para crear la imagen generica que usaran los UE y los alguna otra de las entidades, el resto de archivos de configuración y asibles se encuentran en la carpeta ```horse-complete```.
### Ficheros Importantes
- __/5G-lab/pqreact-lab.yaml__: describe la topologia que se va a lanzar.
- __/5G-core/horse-deployment/lab-config.yaml__: ejecuta dentro de los pods los ficheros ```.py``` que se encuentran en la carpeta configuracion.
- __/5G-core/configuracion/__: en este directorio se encuentran todos los archivos de python que se van a ejecutar dentro de cada uno de los podscd que lanzemos.
### Modificar imagen generic
Se pueden añadir elementos al ```dockerfile``` para añadirlos a la imagen generic que generamos. Una vez actualizado el ```dockerfile``` lo siguiente será compilar/crear la imagen y añadirla al repositorio de ```kne``` para que pueda acceder a ella cuando despleguemos la arquitectura. Para ello podemos utilizar los siguientes comandos:
```
docker build -t generic .
kind load docker-image generic:latest --name=kne
```
Se pueden consultar las imagenes a las que tiene acceso el cluster de kind con el siguiente comando:
```
docker exec -it kne-control-plane crictl images
```
¡¡¡SI NO RECONOCE EL COMANDO KIND!!!
A veces pasa que go se quita del `PATH` y como kind dependende de go no reconoce el comando. Se puede comrpobar si el error viene de ahi haciendo un `go version` y ver si reconoce el comando `go`. Para solucionarlo hacer `ls` en `/home/ubuntu` para ver si sigue estando la carpeta `go`. Si es así basta con lanzar los siguientes comandos para volver a meter go en el PATH:
```
export PATH=$PATH:/usr/local/go/bin
export PATH=$PATH:$(go env GOPATH)/bin
```
## Despliegue del entorno
Asumimos que ya está desplegado KNE siguiendo las indicaciones de su repositorio de [github](https://github.com/openconfig/kne/blob/main/docs/setup.md). Despues nos vamos a la guia de como [crear una topologia](https://github.com/openconfig/kne/blob/main/docs/create_topology.md) y seguimos los pasos. En nuestro caso estamos usando el `cEOS Controller`, y la imagen ya se encuentra en el cluster de kind, pero en caso de no encontrarla en el directorio `/home/ubuntu` está la imagen en formato `tar`. Para pasarla al cluster de kind bastaria con los siguientes comandos:
```
cat cEOS-lab-4.29.2F.tar | docker import - ceos
kind load docker-image ceos:latest --name=kne
```
Para desplegar la topología lanzamos el siguiente comando
```
kne create pqreact-lab.yaml
```
Para lanzar los archivos de configuración de cada pod:
```
ansible-playbook horse-deployment/lab-config.yaml
```
### Despliegue del entorno 5G
Una vez lanzado todo hay que descargar y [desplegar las soluciones de 5G-core y de UE/RAN en los pods.](https://github.com/s5uishida/open5gs_5gc_ueransim_sample_config)
Seguimos los pasos de ese enlace para desplegar el entorno 5G. Puntos a tener en cuenta:
- Mongo por algun motivo no se crea como servicio, de modo que hay que dejarlo ejecutandose en una terminal. Para ello usamos el comando ```tmux``` que nos crea una terminal. Dentro de esta nueva terminal ejecutamos el comando ```mongod --config /etc/mongod.conf```. Para salir de esa terminal y que se quede ejecutandose hacemos ```ctrl+b``` y luego ```d```.
- Importante crear en el UPF la interfaz de red
```
ip tuntap add name ogstun mode tun
ip addr add 10.45.0.1/16 dev ogstun
ip link set ogstun up
iptables -t nat -A POSTROUTING -s 10.45.0.0/16 ! -o ogstun -j MASQUERADE
```
Si dentro del contenedor/pod sale un error al intentar crear el tuntap, los siguientes comandos parecen solucionar el problema:
```
mkdir -p /dev/net
mknod /dev/net/tun c 10 200
chmod 600 /dev/net/tun
```
- Se adjuntan a continuación capturas de las configuraciones:
- 5g-core
```/open5gs/install/etc/open5gs/amf.yaml```

```/open5gs/install/etc/open5gs/nrf.yaml```

```/open5gs/install/etc/open5gs/smf.yaml```

- UPF
```/open5gs/install/etc/open5gs/upf.yaml```

- gNB1
```/UERANSIM/config/open5gs-gnb.yaml```

- UE-2
```/UERANSIM/config/open5gs-ue.yaml```

- Para ejecutar los servicios
- 5g-core
```
./install/bin/open5gs-nrfd &
sleep 2
./install/bin/open5gs-scpd &
sleep 2
./install/bin/open5gs-amfd &
sleep 2
./install/bin/open5gs-smfd &
./install/bin/open5gs-ausfd &
./install/bin/open5gs-udmd &
./install/bin/open5gs-udrd &
./install/bin/open5gs-pcfd &
./install/bin/open5gs-nssfd &
./install/bin/open5gs-bsfd &
```
- UPF
```
./install/bin/open5gs-upfd &
```
- gNB
```
cd UERANSIM/build
./nr-gnb -c ../config/open5gs-gnb.yaml
```
- UE
```
cd UERANSIM/build
./nr-ue -c ../config/open5gs-ue.yaml
```
- Para registrar el UE hay que lanzar el servicio web desde 5g-core. Se necesita ```nodejs``` en una versión igual o superior a la 20. Para lanzar el servicio web entramos en la carpeta ```webui```. Si es la primera vez que lo desplegamos hay que lanzar antes el siguiente comando ```npm ci```. Por último, para iniciar el servicio ```npm run dev```.
- Para hacer el redireccionamiento para poder acceder desde el navegador del ordenador hay que hacer dos redireciones. La primera la hacemos haciendo un ```kubectl apply -f webui-service.yaml``` desde la carpeta 5g-lab. Para la segunda nos abrimos una terminal y ejecutamos el siguiente comando ```ssh -L localhost:8888:172.18.0.2:30300 ubuntu@192.168.159.75```. Una vez hecho esto podremos acceder desde nuestro navegador accediendo a la url ```http://localhost:8888/```
- Para el exponer el servicio web en el entorno del 5TONIC -> ``` ssh -L localhost:8888:10.244.0.80:9999 ubuntu@10.4.35.103```, donde 10.244.0.80 es la ip asignada al pod, que se obtiene con el comando ```kubectl get pods -o wide```
Una vez hecho todo esto nos metemos en una terminal del UE que estemos usando y para comprobar que funcione todo correctamente. Primero podemos ver que nos haya creado la interfaz de red y su IP asociada. Deberia salir algo similar a esto:
```
# ip addr show
...
21: uesimtun0: <POINTOPOINT,PROMISC,NOTRAILERS,UP,LOWER_UP> mtu 1400 qdisc fq_codel state UNKNOWN group default qlen 500
link/none
inet 10.45.0.2/32 scope global uesimtun0
valid_lft forever preferred_lft forever
inet6 fe80::3d90:4d95:c73e:89da/64 scope link stable-privacy
valid_lft forever preferred_lft forever
...
```
Para comprobar la conectividad, desde la misma terminal del UE lanzamos ```ping google.com -I uesimtun0 -n```
### Despliegue de las soluciones de IPSEC
#### strongSwan
##### 1. *Clasico/Sin PQC:*
Primero asegurarnos de que en el fichero ```/etc/sysctl.conf``` los siguientes parametros:
```
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
```
Para aplicar los cambios ```sysctl -p```
Instalamos los siguientes paquetes:
```
apt install strongswan strongswan-pki libcharon-extra-plugins libcharon-extauth-plugins libstrongswan-extra-plugins libtss2-tcti-tabrmd0 -y
```
Una vez instalados los paquetes tendremos que configurar varios archivos para poder establecer el tunel IPSec. Hay que generar un PSK para el archivo de secrets. Se puede crear con el siguiente comando:
```
head -c 24 /dev/urandom | base64
```
Ejemplos de la configuración en el escenario para generar el tunel entre secgw-11 y secgw-12:
* SecGW 11:
```
# cat /ect/ipsec.conf
...
config setup
charondebug="all"
strictcrlpolicy=yes
uniqueids=yes
# Add connections here.
conn UE-to-Core
authby=secret
left=%defaultroute
leftid=10.10.0.25
leftsubnet=10.1.0.0/24
right=10.10.0.31
rightsubnet=10.0.24.0/24
ike=aes256-sha2_256-modp1024!
esp=aes256-sha2_256!
keyingtries=0
ikelifetime=1h
lifetime=8h
dpddelay=30
dpdtimeout=120
dpdaction=restart
auto=start
conn UE-to-UPF
authby=secret
left=%defaultroute
leftid=10.10.0.25
leftsubnet=10.1.0.0/24
right=10.10.0.31
rightsubnet=10.0.25.0/24
ike=aes256-sha2_256-modp1024!
esp=aes256-sha2_256!
keyingtries=0
ikelifetime=1h
lifetime=8h
dpddelay=30
dpdtimeout=120
dpdaction=restart
auto=start
...
# cat /etc/ipsec.secrets
...
10.10.0.25 10.10.0.31 : PSK "i+GXcw0ZUtjug8mhMzMTkSE2k69H/yK5"w
```
* SecGW 12:
```
# cat /etc/ipsec.conf
...
config setup
charondebug="all"
strictcrlpolicy=yes
uniqueids=yes
# Add connections here.
conn siteA-to-siteB
authby=secret
left=%defaultroute
leftid=10.10.0.31
leftsubnet=10.0.24.0/24
right=10.10.0.25
rightsubnet=10.1.0.0/24
ike=aes256-sha2_256-modp1024!
esp=aes256-sha2_256!
keyingtries=0
ikelifetime=1h
lifetime=8h
dpddelay=30
dpdtimeout=120
dpdaction=restart
auto=start
conn UE-to-Core
authby=secret
left=%defaultroute
leftid=10.10.0.31
leftsubnet=10.0.25.0/24
right=10.10.0.25
rightsubnet=10.1.0.0/24
ike=aes256-sha2_256-modp1024!
esp=aes256-sha2_256!
keyingtries=0
ikelifetime=1h
lifetime=8h
dpddelay=30
dpdtimeout=120
dpdaction=restart
auto=start
...
# cat /etc/ipsec.secrets
...
10.10.0.31 10.10.0.25 : PSK "i+GXcw0ZUtjug8mhMzMTkSE2k69H/yK5"
```
Una vez hemos modificado los archivos de configuración, podemos iniciar el tunel IPSec con el comando ```ipsec start```. Para comprobar el estado del tunel podemos usar el comando ```ipsec status``` o ```ipsec statusall```. Para comprobar que todo funciona correctamente podemos lanzar un ping desde el gNB1 *(en este caso)* hasta el 5G-core o el UPF. Si nos ponemos a escuchar el trafico en un SecGW con un ```tcpdump -i any icmp or esp``` podemos ver como se envia el ping y este va encapsulado:
```
root@secgw-11:/home/cognet# tcpdump -i any icmp or esp
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
12:31:22.773690 eth1 In IP 10.1.0.29 > 10.0.24.15: ICMP echo request, id 11821, seq 1, length 64
12:31:22.773906 eth2 Out IP 10.10.0.25 > 10.10.0.31: ESP(spi=0xc00d79de,seq=0x1), length 136
12:31:22.774253 eth2 In IP 10.10.0.31 > 10.10.0.25: ESP(spi=0xc285643d,seq=0x1), length 136
12:31:22.774253 eth2 In IP 10.0.24.15 > 10.1.0.29: ICMP echo reply, id 11821, seq 1, length 64
12:31:22.774335 eth1 Out IP 10.0.24.15 > 10.1.0.29: ICMP echo reply, id 11821, seq 1, length 64
12:31:23.789321 eth1 In IP 10.1.0.29 > 10.0.24.15: ICMP echo request, id 11821, seq 2, length 64
12:31:23.789398 eth2 Out IP 10.10.0.25 > 10.10.0.31: ESP(spi=0xc00d79de,seq=0x2), length 136
12:31:23.789582 eth2 In IP 10.10.0.31 > 10.10.0.25: ESP(spi=0xc285643d,seq=0x2), length 136
12:31:23.789582 eth2 In IP 10.0.24.15 > 10.1.0.29: ICMP echo reply, id 11821, seq 2, length 64
12:31:23.789609 eth1 Out IP 10.0.24.15 > 10.1.0.29: ICMP echo reply, id 11821, seq 2, length 64
12:31:24.813283 eth1 In IP 10.1.0.29 > 10.0.24.15: ICMP echo request, id 11821, seq 3, length 64
12:31:24.813364 eth2 Out IP 10.10.0.25 > 10.10.0.31: ESP(spi=0xc00d79de,seq=0x3), length 136
...
root@secgw-12:/home/cognet# tcpdump -i any icmp or esp
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
12:31:22.773910 eth1 In IP 10.10.0.25 > 10.10.0.31: ESP(spi=0xc00d79de,seq=0x1), length 136
12:31:22.773910 eth1 In IP 10.1.0.29 > 10.0.24.15: ICMP echo request, id 11821, seq 1, length 64
12:31:22.774011 eth2 Out IP 10.1.0.29 > 10.0.24.15: ICMP echo request, id 11821, seq 1, length 64
12:31:22.774187 eth2 In IP 10.0.24.15 > 10.1.0.29: ICMP echo reply, id 11821, seq 1, length 64
12:31:22.774250 eth1 Out IP 10.10.0.31 > 10.10.0.25: ESP(spi=0xc285643d,seq=0x1), length 136
12:31:23.789401 eth1 In IP 10.10.0.25 > 10.10.0.31: ESP(spi=0xc00d79de,seq=0x2), length 136
12:31:23.789401 eth1 In IP 10.1.0.29 > 10.0.24.15: ICMP echo request, id 11821, seq 2, length 64
12:31:23.789457 eth2 Out IP 10.1.0.29 > 10.0.24.15: ICMP echo request, id 11821, seq 2, length 64
12:31:23.789551 eth2 In IP 10.0.24.15 > 10.1.0.29: ICMP echo reply, id 11821, seq 2, length 64
12:31:23.789580 eth1 Out IP 10.10.0.31 > 10.10.0.25: ESP(spi=0xc285643d,seq=0x2), length 136
...
```
Si desplegamos el entorno 5G se puede ver que las comunicaciones entre el gNB y el 5G-core/UPF van encriptadas.
##### 2. *PQC:*
Para usar strongSwan con PQC necesitamos instalar la versión 6.0.0 o posteriores. Para ello podemos seguir los pasos que nos indican en su [documentación](https://docs.strongswan.org/docs/latest/install/install.html). Los pasos son los siguientes:
```
apt install make cmake gcc g++ wget bzip2 libssl-dev
wget https://download.strongswan.org/strongswan-x.x.x.tar.bz2
tar xjf strongswan-x.x.x.tar.bz2
cd strongswan-x.x.x
./configure --enable-ml
make
make install
```
Hay que habilitar `ml` que es el plugin que permite utilizar PQC en strongSwan.
Para usarlo hay que lanzar el charon, que se encuntra en la carpeta `/usr/local/libexec/ipsec`. Lo ejecutamos y ya podemos usar el comando `swanctl`.
Si lanzamos `swanctl --list-algs` podemos ver los algoritmos que nos permite usar para construir el tunel IPSec.
```
# swanctl --list-algs
...
ke:
MODP_3072[openssl]
MODP_4096[openssl]
MODP_6144[openssl]
MODP_8192[openssl]
MODP_2048[openssl]
MODP_2048_224[openssl]
MODP_2048_256[openssl]
MODP_1536[openssl]
MODP_1024[openssl]
MODP_1024_160[openssl]
MODP_768[openssl]
MODP_CUSTOM[openssl]
ECP_256[openssl]
ECP_384[openssl]
ECP_521[openssl]
ECP_224[openssl]
ECP_192[openssl]
ECP_256_BP[openssl]
ECP_384_BP[openssl]
ECP_512_BP[openssl]
ECP_224_BP[openssl]
CURVE_25519[openssl]
CURVE_448[openssl]
ML_KEM_512[ml]
ML_KEM_768[ml]
ML_KEM_1024[ml]
...
```
Se pueden ver que los ultimos algoritmos son del plugin ml y son los que usaremos. Estos corresponden al [FIPS 203](https://csrc.nist.gov/pubs/fips/203/final)
A continuación configuraremos el archivo `/usr/local/etc/swanctl/swanctl.conf`, donde definiremos las conexiones. Ejemplo de configuración para secgw-11:
```
connections {
gw-gw {
local_addrs = 10.10.0.25
remote_addrs = 10.10.0.31
local {
auth = psk
id = 10.10.0.25
}
remote {
auth = psk
id = 10.10.0.31
}
children {
net-net {
local_ts = 10.1.0.0/24
remote_ts = 10.0.24.0/24,10.0.25.0/24
#updown = /usr/local/libexec/ipsec/_updown iptables
rekey_time = 5400
rekey_bytes = 500000000
rekey_packets = 1000000
esp_proposals = aes256-sha256-mlkem512
}
}
version = 2
mobike = no
reauth_time = 10800
proposals = aes256-sha256-x25519-mlkem512
}
}
secrets {
ike-1 {
id1 = 10.10.0.25
id2 = 10.10.0.31
secret="zOD8I522Vvt6zUt5rkpHRA4kt8YM64+C"
}}
```
Una vez realizada la configuración podemos cargarla con el comando `swanctl --load-all` en ambas maquinas. Para iniciar el tunel basta con lanzar en una de las máquinas el comando `swanctl -i --child net-net`. Podemos ver si se ha creado de la siguiente forma:
```
# swanctl --list-sas
gw-gw: #4, ESTABLISHED, IKEv2, c4909f45747c2b01_i* b8aa46f78ad68702_r
local '10.20.0.69' @ 10.20.0.69[500]
remote '10.20.0.39' @ 10.20.0.39[500]
AES_CBC-256/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/CURVE_25519
established 227s ago, reauth in 9767s
net-net: #6, reqid 1, INSTALLED, TUNNEL, ESP:AES_CBC-256/HMAC_SHA2_256_128/ML_KEM_512
installed 207s ago, rekeying in 5014s, expires in 5733s
in c9dd30ca, 252 bytes, 3 packets, 2s ago
out c3e481e7, 252 bytes, 3 packets, 2s ago
local 10.2.0.0/24
remote 10.0.24.0/24
```
Vemos que se ha creado adecuadamente el tunel y podemos ver que los tres paquetes del ping que he hecho para comprobarlo han pasado por el tunel.
Para parar el tunel se utiliza el siguiente comando `swanctl -t --child net-net`
### IPERF
Para realizar las pruebas desplegamos un server iperf en la maquina que hace de gateway y lanzamos el cliente iperf en el ue usando la interfaz creada por el ue.
Lanzar el server iperf -> `iperf3 -s`
Lanzar la petición desde el UE (cambiar la ip del `--bind`)-> `iperf3 -c 10.4.0.1 --bind 10.45.0.2 --bind-dev uesimtun0`
## Información extra
Para borrar la topología lanzamos el comando
```
kubectl delete ns pqreact-lab
```