One application that I’ve done some years ago was a GTP dialer for Linux/OSX OS. It’s an application that basically creates a GTP tunnel with a GGSN, and then the IP received in the CreatePDPContext Response is set as tunnel interface in the machine. After that we set the default route to the tunnel interface (keeping always a /32 route for the tunnel endpoint towards the previous default gateway) and we can use the GTP tunnel to send and receive traffic from the internet, or to whatever networks the APN give us connectivity.
It’s different from my SGSN/MME/SGW Emulator because that tool is focused on the control plane side of things, while the GTP dialer is just like a VPN dialer, and the focus is the user plane.
It’s very useful to perform service tests in the GGSN/PGW, since we can use any application in the laptop (ex. web browser), and it also supports all PDP Types (IPv4, IPv6 or IPv4v6).
I have a Raspberry in my house and I was thinking in doing some kind of http/https proxy or implementing some tunneling protocol just to be able to access the internet using my home IP. This way I could for example, use services that are only available in my home country when I’m abroad.
Then I notice that I already had this GTP dialer that is in its own way a tunneling mechanism…. So I come up with the following idea:
What if I do a simple GGSN in my Raspberry Pi that could be used with my GTP dialer? I can be anywhere in the world with my laptop, connected to a Wlan or Ethernet network, and as long I have internet access, I can connect and establish a GTP tunnel to my Raspberry Pi in my house, which will give me a private IP from my internal network, and then all the traffic from my laptop will be sent encapsulated in GTP to the Raspberry IP, and then stripped and NATted in my Home Gateway (HGW) to the internet?
Sounds easy, right?
After this initial idea, I thought that I could extend it and allow more than one connection at the same time (multiple PDPs from different clients), and using DHCP for IP address allocation in the HGW. For example my internal network is the usual 192.168.1.0/24. Most of these addresses are available in the DHCP server of my HGW to be assigned to machines that use my Wlan or Ethernet network. I have a 200Mbits WAN connection to my service provider, but the Raspberry Pi is connected via Ethernet cable with a 100Mbits speed, so I think that up to 10 connections could have a decent bandwidth.
There are several technical issues that need to be addressed:
- If the Raspberry Pi uses its MAC address for all these communications, the DHCP server will assign always the same IP address, so for each one of these PDP requests arriving at the Raspberry Pi, a different MAC address should be used, so that the HGW assigns a different IPs. To forge these MAC addresses, we need a RAW socket for the uplink packets and a RAW socket in promiscuous mode for the downlink packets, since the Raspberry Pi needs to listen and process the packets sent by the HGW to these fictitious MAC addresses.
- The Raspberry needs to track all ARP requests in internal LAN, since it must answers in behalf of all internal IP assigned to the current active PDP sessions, and answer those ARP Request with the correct MAC Address. This can be done with a RAW socket in promiscuous mode.
- The Raspberry Pi needs to track the DHCP timers for all IPs assigned to the PDP sessions. It needs to renew the IP at half the lease time if the PDP is still up, and release the IP when the PDP is deleted.
- Port forwarding for GTP-C and GTP-U must be configured in the HGW (e.g. UDP ports 2123 and 2152)
- The GTP dialer, can be behind a NAT device. In the normal GTP-U operation, uplink packets from a SGSN are sent to UDP port 2152 in the GGSN, and downlink packets are sent from the GGSN to the UDP Port 2152 in the SGSN, and the source port can be any port. This can be problematic, because port 2152 could not be open in the NAT, or if it’s open, it can be assigned to a different internal client that is also behind the same NAT device. To overcome this, the GGSN can detect if the client is behind a NAT by comparing the source IP with the GSN IP Address for Control and Data received in the CreatePDPContext Request message. If they are different, then the client is behind a NAT device, so the GGSN instead of sending the downlink GTP-U packets to UDP port 2152, it will send it to the source port of the GTP-U packets coming from the GTP dialer. Since the GTP dialer uses UDP port 2152 as source port for all uplink GTP-U packets, the NAT translation will guarantee that all downlink packets sent by the GGSN to the source port previously received in the uplink GTP-U packets, will be delivered to the GTP dialer. Since this traffic is UDP, the translation timeout is usually small (5 minutes). So we have the risk that this translation expires, and a new source port is assigned later on. To overcome this, the GGSN needs to always compare the GTP-U source port of the uplink packets, and if it’s different, it should update it in the session table.
The control plane flow for each session establishing is the following:
Next picture, shows the user plane flow of an uplink packet:
You can check this trace that I took in the Raspberry Pi of a session where you can see all these flows.
No comments:
Post a Comment