Here’s a puzzle for you networking specialists:

I’m coding an IP tunnel for our laser communication system. Basically it’s a pair of lasers that send / receive raw serial data, and I’m coding a simple TUN wrapper to send/receive IP packets over the laser link. Think of it as PPP but customized for the idiosyncrasies of our laser system.

It works fine: I have one laser connected to one machine with one instance of my IP tunnel software running on that machine, the same setup on another machine, and I can network just fine between the two.

But here’s my problem: those machines are at work and I’m currently sitting at home and working remotely, the second machine has crashed and I have no intention to go to the office just to reboot the damn thing.

But all is not lost!

The first machine happens to have another, unused laser aimed at the same target connected to it. Technically, I can open a serial terminal on one laser’s serial device file, another serial terminal on the second laser’s serial device file, and send / receive data between the two - to / from the same machine.

My question is this: can I somehow create two TUN network interfaces - one for one laser, one for the other laser - on the same machine, and somehow configure them so one is only reachable through the tunnel and not directly?

Or more concretely, here are the two tunnels setup on the first machine:

tun10: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500  
        inet 172.17.3.10  netmask 255.255.255.0  destination 172.17.3.10  
        inet6 fe80::48a7:298c:c6dc:bae  prefixlen 64  scopeid 0x20<link>  
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 500  (UNSPEC)  
        RX packets 4  bytes 192 (192.0 B)  
        RX errors 0  dropped 0  overruns 0  frame 0  
        TX packets 5  bytes 240 (240.0 B)  
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0  

tun11: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500  
        inet 172.17.3.11  netmask 255.255.255.0  destination 172.17.3.11  
        inet6 fe80::82b2:44f6:d510:c227  prefixlen 64  scopeid 0x20<link>  
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 500  (UNSPEC)  
        RX packets 2  bytes 96 (96.0 B)  
        RX errors 0  dropped 0  overruns 0  frame 0  
        TX packets 4  bytes 192 (192.0 B)  
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0  

I want to telnet to 172.17.3.10 through 172.17.3.11 and vice-versa. But of course, as it is now, if I telnet to either of those IPs, the kernel basically talks to itself and doesn’t route anything out.

Naturally, I could setup a virtual machine and install a guest Linux OS just to run the second tunnel. But it seems like a sledgehammer approach to what should be a simple configuration job.

Can it be done? I can’t think of a way. But then I’m not much of a networking guy 🙂

  • litchralee@sh.itjust.works
    link
    fedilink
    English
    arrow-up
    3
    ·
    edit-2
    6 days ago

    Let me make sure I understand the background info. Before things crashed, you had two machines that shared a two-way laser serial link, and so your testing involved sending from one machine to the other, as a way to exercise the TUN driver. Now that the second machine is dead, you wish to light up a spare two-way laser serial link. But rather than connecting to the second (dead) machine or some third machine, this spare link is functionally a “loop back” to the existing machine, the one that’s still alive. And you wish to continue your testing with this revised setup, to save yourself from having to commute to the office just to reboot the second machine.

    Do I have that right? If so, firstly, it’s a Saturday in all parts of the world lol. But provided that you’re getting sufficient rest from work, I will continue.

    As it stands, you are correct that the Linux machine will prefer to pass traffic internally, when it sees that the destination is local. We can try to defeat this, but it’s very much like cutting against the grain. This involves removing the kernel stack’s tendency to route packets locally, but only for the traffic going to/from the TUN interfaces. But if you get this wrong, you might lose access to the machine, and now you have 0/2 working machines…

    IMO, a better solution would be to move at least one of the TUN interfaces into its own “network namespace”. This is the Linux kernel’s idea of separate network stacks, and is one of the constituent technologies used to enable containers (which are like VMs but more lightweight). Since you only require the traffic to exit on one TUN netif and come back in on the other TUN netif, this could work.

    First, you create a new namespace (I’ll call it bobby), then you move tun11 into the bobby ns, and then you run all your commands in a shell that’s spawned within the bobby ns. The last part means you have access to all the files and your filesystem, but because you’re in a separate network namespace, you will not see the same netifs that would show up in the “default” namespace.

    Here are the commands, but you can check this against this reference too:

    ip netns add bobby
    ip link set tun11 netns bobby
    ip netns exec bobby /bin/bash
    

    From inside this shell, that’s how you access tun11 (and only tun11). You’ll want to open a second SSH connection to your remote machine, which will naturally be in the “default” namespace and will allow you access to the tun10 netif (but not tun11).

    Good luck!

    • ExtremeDullard@piefed.socialOP
      link
      fedilink
      English
      arrow-up
      2
      ·
      6 days ago

      Do I have that right?

      Perfect understanding 🙂

      If so, firstly, it’s a Saturday in all parts of the word lol. But provided that you’re getting sufficient rest from work, I will continue.

      This is my idea of fun.

      No worries, I don’t work overtime unless I’m having fun doing it. I’m old enough to know better than to waste my life at work. It just so happens that my work is also my hobby to a large extent.

      a better solution would be to move at least one of the TUN interfaces into its own “network namespace”

      Thanks! I’ll dig into that right now.

      • ExtremeDullard@piefed.socialOP
        link
        fedilink
        English
        arrow-up
        2
        ·
        6 days ago

        a better solution would be to move at least one of the TUN interfaces into its own “network namespace”

        Okay so I did that, ran a shell in the alternate namespace, but the networking was pretty much blank. So I gave tun11 an IP again with ifconfig, then added a host route to the first machine, and ta-da: I can SSH to tun10 through the serial loop. Nice!

        Thanks, I learned something new today.

        BTW, from your username, are you familiar with !Dullsters@dullsters.net ?

        I am a member of !dull_mens_club@lemmy.world 🙂 There’s more than one venue for dull men.

        • litchralee@sh.itjust.works
          link
          fedilink
          English
          arrow-up
          1
          ·
          6 days ago

          So I gave tun11 an IP again with ifconfig, then added a host route to the first machine

          Out of curiosity, what were these commands? I’m a bit confused because I figured that just adding the IP+mask would be sufficient, without having to explicitly add a host route.

          • ExtremeDullard@piefed.socialOP
            link
            fedilink
            English
            arrow-up
            1
            ·
            6 days ago

            I did this (after the two tun devices were up):

            ip netns add tun11
            ip link set tun11 netns tun11
            ip netns exec tun11 /usr/bin/bash
            ifconfig tun11 172.17.3.11
            route add -host 172.17.3.10 gw 172.17.3.11
            
            • litchralee@sh.itjust.works
              link
              fedilink
              English
              arrow-up
              1
              ·
              6 days ago

              Ah, I see. That works too, but I usually find it easier to set the subnet mask for the first interface, so that there’s no hard-coding of a route to every intended destination, even if it’s just one.

              With ifconfig, that might look like:

              ifconfig tun11 172.17.3.11 netmask 255.255.255.0
              

              With the moden “ip” command, it’s even less typing:

              ip addr add 172.17.3.11/24 dev tun11