OpenVPN / tap-windows6

Windows TAP driver (NDIS 6)
Other
785 stars 237 forks source link

IPV4 - routes, and such - confused #111

Open duaneellissd opened 4 years ago

duaneellissd commented 4 years ago

I'm not getting any IPV4 packets out of the TUN driver in P2P mode. I don't understand why and I am a bit confused.

It seems that no matter what I do, I do not get IPv4 Traffic - I see IPv6 but no IPv4

What I don't know how to do is determine the route windows wants to use.

Interface configuration:

Unknown adapter Local Area Connection:

   Connection-specific DNS Suffix  . :
   Description . . . . . . . . . . . : TAP-Windows Adapter V9
   Physical Address. . . . . . . . . : 00-FF-0D-20-6E-9E
   DHCP Enabled. . . . . . . . . . . : No
   Autoconfiguration Enabled . . . . : Yes
   Link-local IPv6 Address . . . . . : fe80::456:c9a:9c24:6df3%17(Preferred)
   IPv4 Address. . . . . . . . . . . : 10.168.42.1(Preferred)
   Subnet Mask . . . . . . . . . . . : 255.255.255.252
   Default Gateway . . . . . . . . . :
   DHCPv6 IAID . . . . . . . . . . . : 285277965
   DHCPv6 Client DUID. . . . . . . . : 00-01-00-01-25-2F-CD-E0-98-E7-43-7A-1E-F9
   DNS Servers . . . . . . . . . . . : fec0:0:0:ffff::1%1
                                       fec0:0:0:ffff::2%1
                                       fec0:0:0:ffff::3%1
   NetBIOS over Tcpip. . . . . . . . : Enabled

I read in the OpenVPN source code that, in P2P mode, the network mask must be exactly 255.255.255.252 - so that's what I have.

I also see in the same code, the IP address for the WINDOWS side (last bits) must be 1 or 2, and the REMOTE side must be the other 2 or 1.

Thus, I configured the windows interface as 10.168.42.1, my remote side is 10.168.42.2

The ROUTING TABLES are as follows:

IPv4 Route Table
===========================================================================
Active Routes:
Network Destination        Netmask          Gateway       Interface  Metric
          0.0.0.0          0.0.0.0      10.168.99.1    10.168.99.195     25
      10.168.42.0  255.255.255.252         On-link       10.168.42.1    281
      10.168.96.0    255.255.252.0         On-link     10.168.99.195    281
    10.168.99.195  255.255.255.255         On-link     10.168.99.195    281
    10.168.99.255  255.255.255.255         On-link     10.168.99.195    281
        127.0.0.0        255.0.0.0         On-link         127.0.0.1    331
        127.0.0.1  255.255.255.255         On-link         127.0.0.1    331
  127.255.255.255  255.255.255.255         On-link         127.0.0.1    331
      169.254.0.0      255.255.0.0         On-link     169.254.13.25    281
    169.254.13.25  255.255.255.255         On-link     169.254.13.25    281
  169.254.255.255  255.255.255.255         On-link     169.254.13.25    281
     192.168.56.0    255.255.255.0         On-link      192.168.56.1    281
     192.168.56.1  255.255.255.255         On-link      192.168.56.1    281
   192.168.56.255  255.255.255.255         On-link      192.168.56.1    281
    192.168.125.0    255.255.255.0         On-link     192.168.125.1    291
    192.168.125.1  255.255.255.255         On-link     192.168.125.1    291
  192.168.125.255  255.255.255.255         On-link     192.168.125.1    291
    192.168.162.0    255.255.255.0         On-link     192.168.162.1    291
    192.168.162.1  255.255.255.255         On-link     192.168.162.1    291
  192.168.162.255  255.255.255.255         On-link     192.168.162.1    291
        224.0.0.0        240.0.0.0         On-link         127.0.0.1    331
        224.0.0.0        240.0.0.0         On-link      192.168.56.1    281
        224.0.0.0        240.0.0.0         On-link     192.168.125.1    291
        224.0.0.0        240.0.0.0         On-link     192.168.162.1    291
        224.0.0.0        240.0.0.0         On-link     10.168.99.195    281
        224.0.0.0        240.0.0.0         On-link     169.254.13.25    281
        224.0.0.0        240.0.0.0         On-link       10.168.42.1    281
  255.255.255.255  255.255.255.255         On-link         127.0.0.1    331
  255.255.255.255  255.255.255.255         On-link      192.168.56.1    281
  255.255.255.255  255.255.255.255         On-link     192.168.125.1    291
  255.255.255.255  255.255.255.255         On-link     192.168.162.1    291
  255.255.255.255  255.255.255.255         On-link     10.168.99.195    281
  255.255.255.255  255.255.255.255         On-link     169.254.13.25    281
  255.255.255.255  255.255.255.255         On-link       10.168.42.1    281
===========================================================================
Persistent Routes:
  None

I have 3 tests I've tried: Method 1: ping 10.168.42.2 - I would expect some activity Method 2: ping -6 -S localipv6address someipv6addressonnetwork Method 3: curl -o foo http://10.168.42.2

For case 2, The IPv6 seems to work using linked local addresse (fe80), and specifying the target address as the same as the ipv6 addres but +1, thus it is on the same IPv6 segment. This works, I see packets out of the tun driver but no IPv4 packets.

cron2 commented 4 years ago

Hi,

On Mon, Mar 30, 2020 at 06:04:17PM -0700, duaneellissd wrote:

I'm not getting any IPV4 packets out of the TUN driver in P2P mode. I don't understand why and I am a bit confused.

This looks like "ARP fail". Try wiresharking on the tun interface to see what happens.

My bet is on "before sending the IPv4 ping, you see an ARP request, which is not answered, thus the IP layer has no idea where on that virtual ethernet it's supposed to send the IPv4 packet to".

You can try to set up startic ARP entries, though I'm not sure if that works right. What OpenVPN does is to program the "gateway" IPv4 address into the tun/tap driver by means of an ioctl(), and so the driver itself answers the ARP request with its own MAC adddress, and then IPv4 can flow.

IPv6 is different because for ND, IPv6 packets are used that are sent to multicast addresses = forwarded everywhere without destination MAC address resolution first.

See openvpn's tun.c, tuntap_set_ptp() for the DeviceIoControl() calls used (git master, but searching for TAP_WIN_IOCTL_CONFIG_TUN should find it in 2.4 as well).

(The .1 / .2 thing is just a simplistic check to ensure "common subnet"

gert -- "If was one thing all people took for granted, was conviction that if you feed honest figures into a computer, honest figures come out. Never doubted it myself till I met a computer with a sense of humor." Robert A. Heinlein, The Moon is a Harsh Mistress

Gert Doering - Munich, Germany gert@greenie.muc.de

duaneellissd commented 4 years ago

Agree it's an ARP problem, I think it is a design limitation -

I am using P2P Mode, not TUN mode. I am not using DHCP, perhaps I should

I would have expected P2P mode to "just work" - I think the problem is described below

I see this in Wireshark:

image

I believe the AUTOIP address (169.254) is the default address given at startup.

When I start the adapter (ie: ioctl(set media state) I see the two gratuitous ARPs

Then later, I try to PING the remote side, I then see the three "Who has" ARP requests, but nothing comes out of the driver into my user space app.

Looking at the code in "device.c" - I find the function ProcessARP() which seems to send the ARP reply, it lives in the txpath.c - it is called under 2 conditions: (A) Line 597 - if DHCP is enabled, I'm not enabling it

    //=====================================================
    // Are we running in DHCP server masquerade mode?
    //
    // If so, catch both DHCP requests and ARP queries
    // to resolve the address of our virtual DHCP server.
    //=====================================================
    if (Adapter->m_dhcp_enabled)
    {
        const ETH_HEADER *eth = (ETH_HEADER *) tapPacket->m_Data;
        const IPHDR *ip = (IPHDR *) (tapPacket->m_Data + sizeof (ETH_HEADER));
        const UDPHDR *udp = (UDPHDR *) (tapPacket->m_Data + sizeof (ETH_HEADER) + sizeof (IPHDR));

        // ARP packet?
        if (packetLength == sizeof (ARP_PACKET)
            && eth->proto == htons (NDIS_ETH_TYPE_ARP)
            && Adapter->m_dhcp_server_arp
            )
        {
            if (ProcessARP(
                    Adapter,

, or case (B) line 662 - This part is confusing the COMMENT states one thing, but the code reads the reverse. - confused.

    //===============================================
    // In Point-To-Point mode, check to see whether
    // packet is ARP (handled) or IPv4 (sent to app).
    // IPv6 packets are inspected for neighbour discovery
    // (to be handled locally), and the rest is forwarded
    // all other protocols are dropped
    //===============================================    if (Adapter->m_tun)
    {
        ETH_HEADER *e;

        e = (ETH_HEADER *) tapPacket->m_Data;

        switch (ntohs (e->proto))
        {
        case NDIS_ETH_TYPE_ARP:

            // Make sure that packet is the right size for ARP.
            if (packetLength != sizeof (ARP_PACKET))
            {
                goto no_queue;
            }

            ProcessARP (
                Adapter,
               .... snip snip ...
cron2 commented 4 years ago

Hi,

On Tue, Mar 31, 2020 at 09:07:24AM -0700, duaneellissd wrote:

Agree it's an ARP problem, I think it is a design limitation -

I am using P2P Mode, not TUN mode. I am not using DHCP, perhaps I should

From windows' point of view, this is an "Ethernet" interface, so whatever you do, you need to make ARP work.

There is no "p2p" mode on the tap driver side (which is why there are restrictions on subnet mask, ip addresses, etc.). It is an ethernet, which needs to do ARP resolution before packets can be sent to the remote side.

It is what it is, whether we like it or not.

There is "TUN" vs "TAP" mode on the TAP driver side, which differs in "will the client application see ethernet headers or just IPv4/IPv6" (in TAP mode, you'd see the ARP).

When I start the adapter (ie: ioctl(set media state) I see the two gratuitous ARPs

Then later, I try to PING the remote side, I then see the three "Who has" ARP requests, but nothing comes out of the driver into my user space app.

Sure, because you need to tell(!) the driver which address to reply to.

It will ignore ARP for all IPv4 addresses except the one that you've ioctl()'ed in.

gert

-- "If was one thing all people took for granted, was conviction that if you feed honest figures into a computer, honest figures come out. Never doubted it myself till I met a computer with a sense of humor." Robert A. Heinlein, The Moon is a Harsh Mistress

Gert Doering - Munich, Germany gert@greenie.muc.de

duaneellissd commented 4 years ago

@gert - Thanks that helps me understand the problem

I also see that that in the P2P case, the adapter->m_tun = TRUE occurs my bad there.

Question 1: what sends the Gratuitous ARP at startup - The driver or windows?

Question 2: Would the fact the driver seems to have 2 IP address (the auto-ip + configured) be the problem, I donot for example see a loop that tests: "For all configured ip address on this driver" thus it would never capture the second address (The first I assume is the AUTO-IP, the SECOND I assume is the configured address)

Question 3: Can you explain the DHCP side? I can turn that on if it helps - I got the impression and I could be wrong - that it needs to work with the remote side DHCP server... or something like that.

In my case my remote does not have a DHCP server, it's a really dumb micro controller running LWIP/SLIP - do I really need to run a dhcp server on that board to make this work?

In any case - If I enable the DHCP - I want to pass the correct parameters - Looking at the driver code, it looks like there are 4 parameters to the DHCP server call. Value 0 - the DHCP address, Value 1 = The DHCP Netmask, value 3 = The DHCP Server IP, Value 4 = the lease time in seconds.

duaneellissd commented 4 years ago

@cron2 (Gert) - Follow up question

Sure, because you need to tell(!) the driver which address to reply to.

Where exactly do I do this, when I configure for P2P - there are 2 parameters

Edit - Its not _at_gert, it is _at_cron2...

cron2 commented 4 years ago

Hi,

On Tue, Mar 31, 2020 at 09:45:58AM -0700, duaneellissd wrote:

@gert - Thanks that helps me understand the problem

I also see that that in the P2P case, the adapter->m_tun = TRUE occurs my bad there.

Question 1: what sends the Gratuitous ARP at startup - The driver or windows?

That's windows - duplicate address detecion and such.

Question 2: Would the fact the driver seems to have 2 IP address (the auto-ip + configured) be the problem, I donot for example see a loop that tests: "For all configured ip address on this driver" thus it would never capture the second address (The first I assume is the AUTO-IP, the SECOND I assume is the configured address)

auto-ip should only be seen if you have configured the interface in windows to "automatic address assignment" - which is only useful if you use the virtual DHCP server built into the TAP driver.

Question 3: Can you explain the DHCP side? I can turn that on if it helps - I got the impression and I could be wrong - that it needs to work with the remote side DHCP server... or something like that.

The TAP driver can pretend to be a DHCP server, to assign the address to the TAP interface. It's enabled by ioctl() calls from the controlling application.

In my case my remote does not have a DHCP server, it's a really dumb micro controller running LWIP/SLIP - do I really need to run a dhcp server on that board to make this work?

No.

In any case - If I enable the DHCP - I want to pass the correct parameters - Looking at the driver code, it looks like there are 4 parameters to the DHCP server call. Value 0 - the DHCP address, Value 1 = The DHCP Netmask, value 3 = The DHCP Server IP, Value 4 = the lease time in seconds.

Not sure which call you are talking about. The relevant bits are the ioctl() calls in openvpn's tun.c code - they demonstrate how to use the driver for the different scenarios.

gert -- "If was one thing all people took for granted, was conviction that if you feed honest figures into a computer, honest figures come out. Never doubted it myself till I met a computer with a sense of humor." Robert A. Heinlein, The Moon is a Harsh Mistress

Gert Doering - Munich, Germany gert@greenie.muc.de

cron2 commented 4 years ago

Hi,

On Tue, Mar 31, 2020 at 09:51:55AM -0700, duaneellissd wrote:

@gert - Follow up question

Sure, because you need to tell(!) the driver which address to reply to.

Where exactly do I do this, when I configure for P2P - there are 2 parameters

  • Parameter 0 - is the local IP - I presume that is the IP address of the local interface, which in my case is 10.168.42.1 (I pass this, the .1 address) - the remote device is 10.168.42.2 (not setting this)

  • Parameter 1 is the netmask, which is 255.255.255.252 (0xfffffffc)

I'm not sure which of the DeviceIoControl()s will effectively store the "other end IP" in the TAP driver, and what exactly "POINT_TO_POINT" will do under the hood - it's a bit convoluted, and in this context, "p2p" might not do what you expect (given that for windows this will always be a network segment with a broadcast address).

Also, OpenVPN calls this "remote_netmask" for a good reason - the variable can be "remote" or "netmask", and in the p2p context it's quite likely "remote". So, put 10.168.42.2 in parameter 1 and see what happens.

gert

-- "If was one thing all people took for granted, was conviction that if you feed honest figures into a computer, honest figures come out. Never doubted it myself till I met a computer with a sense of humor." Robert A. Heinlein, The Moon is a Harsh Mistress

Gert Doering - Munich, Germany gert@greenie.muc.de

duaneellissd commented 4 years ago

Still no joy.

Enabling the DHCP server seems to work, the adapter is configured now :-) via dhcp In wire shark I do see the DHCP requests... and the ack.

And in wireshark I see the ARP requests for .2 but I don't see replies.

Unknown adapter TAP_TUN:

   Connection-specific DNS Suffix  . :
   Description . . . . . . . . . . . : TAP-Windows Adapter V9
   Physical Address. . . . . . . . . : 00-FF-0D-20-6E-9E
   DHCP Enabled. . . . . . . . . . . : Yes
   Autoconfiguration Enabled . . . . : Yes
   Link-local IPv6 Address . . . . . : fe80::456:c9a:9c24:6df3%4(Preferred)
   IPv4 Address. . . . . . . . . . . : 10.168.42.1(Preferred)
   Subnet Mask . . . . . . . . . . . : 255.255.255.252
   Lease Obtained. . . . . . . . . . : Tuesday, March 31, 2020 11:52:07 AM
   Lease Expires . . . . . . . . . . : Wednesday, April 1, 2020 11:52:07 AM
   Default Gateway . . . . . . . . . :
   DHCP Server . . . . . . . . . . . : 10.168.41.255
   DHCPv6 IAID . . . . . . . . . . . : 285277965
   DHCPv6 Client DUID. . . . . . . . : 00-01-00-01-25-2F-CD-E0-98-E7-43-7A-1E-F9
   DNS Servers . . . . . . . . . . . : fec0:0:0:ffff::1%1
                                       fec0:0:0:ffff::2%1
                                       fec0:0:0:ffff::3%1
   NetBIOS over Tcpip. . . . . . . . : Enabled

The ARP output, ie: arp -a -v gives this, I don't know why the .2 address says: Invalid.


C:\Windows\system32>arp -a -v

Interface: 127.0.0.1 --- 0x1
  Internet Address      Physical Address      Type
  224.0.0.22                                  static
  239.255.255.250                             static

Interface: 10.168.42.1 --- 0x4
  Internet Address      Physical Address      Type
  10.168.42.2           00-00-00-00-00-00     invalid
  10.168.42.3           ff-ff-ff-ff-ff-ff     static
  224.0.0.22            01-00-5e-00-00-16     static
  224.0.0.251           01-00-5e-00-00-fb     static
  224.0.0.252           01-00-5e-00-00-fc     static
  239.255.255.250       01-00-5e-7f-ff-fa     static
  255.255.255.255       ff-ff-ff-ff-ff-ff     static