VPN bridge to the local network

    I read the topic habrahabr.ru/blogs/linux/67209 and decided to post here my article, which was previously visible only in the closed corporate Wiki.

    Usually, when creating a VPN, a point-to-point connection is used to some server, or an ethernet tunnel is installed with some server, in which a specific subnet is assigned to the tunnel. The VPN server at the same time performs the functions of routing and filtering traffic to access the local network through the VPN.

    This article considers another approach to creating a virtual network, in which remote systems are included in an existing local subnet, and the VPN server acts as an Ethernet gateway. Using this approach, we still have the ability to filter traffic based on the connection method (for example, use different filters for the local network and for remote users), but the need to configure routing is eliminated, and remote machines connect directly to the local network, see resources, even use broadcast packages without any additional configuration. Through this VPN, they display all the computers on the local Windows network, all available XDMCP servers with XDMCP broadcast, etc.



    Network structure and server setup


    Suppose there is an office with a local network, the IP subnet 192.168.168.0/24 is used . We will include home users in this local network, that is, they will have an address from the same subnet. You need to make sure that they don’t have this subnet at home, and that no systems on the local network have addresses in the range that we will allocate for remote users.

    Core bridge support


    For this technique to work, we need some kernel drivers. This is a universal driver of virtual network interfaces the tun , driver and ethernet-bridge bridge . You can include them in the kernel, or assemble them with modules:

        -> Networking
          -> Networking support (NET [= y])
            -> Networking options
              <*> 802.1d Ethenet Bridging (BRIDGE [= y])
        -> Device Drivers
          -> Network device support (NETDEVICES [= y])
            <*> Universal TUN / TAP device driver support (TUN [= y])
    

    If they will be assembled by modules, you must either enable automatic loading of modules in the kernel, or load them yourself before setting up a VPN connection.

    Software


    The server will require OpenVPN and utilities to service the bridge. In Gentoo, they are assembled as follows:

      emerge net-misc / bridge-utils net-misc / openvpn
    


    When using> = sys-apps / baselayout-1.12.6 this is enough, for older versions, special utilities will be required to service tun / tap devices:

      emerge sys-apps / usermode-utilities
    


    Network configuration


    Suppose eth2 is the interface to which the local network is connected, with the assigned address 192.168.168.254. Its setup looked something like this:

      config_eth2 = ("192.168.168.254/24")
    


    Since he will participate in the bridge, he does not need to assign addresses. Also, the newly created virtual interface tap0 is involved in the bridge, which is also not assigned any address. The address used by eth2 is now assigned to the br0 bridge:

      config_eth2 = ("null")
      tuntap_tap0 = "tap"
      config_tap0 = ("null")
      depend_br0 () {
        need net.tap0 net.eth2
      }
      # specify existing interfaces, combining them into a bridge
      bridge_br0 = "eth2 tap0"
      # either, you can dynamically connect newly appearing interfaces there
      # bridge_add_eth2 = "br0"
      config_br0 = ("192.168.168.254/24")
    


    You also need to create configuration scripts for the specified interfaces:

      cd /etc/init.d
      ln -s net.lo net.eth2
      ln -s net.lo net.tap0
      ln -s net.lo net.br0
    


    It is enough to automatically load only the br0 interface. depend_br0 () will automatically raise all the others it needs to work:

      rc-update add net.br0 default
      /etc/init.d/net.eth2 stop
      /etc/init.d/net.br0 start
    


    Creating OpenVPN keys


    We will authorize clients through RSA keys of OpenSSL. To simplify the process, we prepared several init scripts:

      cd / usr / share / openvpn / easy-rsa /
    


    There is a vars file in which we will add the general values:

      nano vars
    


    At the bottom of this file, we populate our variables:

      export KEY_COUNTRY = "RU"
      export KEY_PROVINCE = "Voronezh oblast"
      export KEY_CITY = "Boguchar"
      export KEY_ORG = "OrganiZationnAme"
      export KEY_EMAIL = "root@oza.ru"
    


    We load the variables from this file and build the CA (Certificate Authority):

      source ./vars
      ./clean-all
      ./build-ca
    


    Server key


    To generate a server key named office, use the following command:

      ./build-key-server office
    


    The question “Common Name” must be answered with the server name (in our case, office). The two questions at the end of “Sign the certificate? [y / n] "and" 1 out of 1 certificate requests certified, commit? [y / n] "we answer" y ".

    If necessary, it will be possible to create additional server keys. For example, it can be backup access servers to increase the reliability of the system. They are created by the same command, before it you need to execute source ./vars.

    Diffie Hellman Parameters

    There is nothing extra to do here, but you have to wait.

      ./build-dh
    


    This file is needed only on the server.

    Customer keys


    Each client needs to give his own key. For a client named client, the key is created by the command

      ./build-key client
    


    We answer the question “Common Name” with the name of the client (in this case, client). At the end, we answer two questions in agreement.

    We transfer the generated keys and certificates to clients through a secure channel. If necessary, you can create more keys with the same command. Before starting it, you need to load the environment - execute source ./vars.

    Setting up and starting the OpenVPN service


    To start, use the following server configuration (file /etc/openvpn/openvpn.conf):

      # This port is recommended by IANA for OpenVPN. You can transfer it to another port, but secrecy will not increase - it is still the first thing it is recognized that it is OpenPVN.
      port 1194
      # OpenVPN can use tcp and udp as a transport protocol, udp is preferable
      proto udp
      # The virtual interface that we included in the bridge is certainly of type tap (you can not emulate Ethernet through tun)
      dev tap0
      # Root self-signed CA certificate
      ca /etc/openvpn/keys/ca.crt
      # Certificate and server secret key. crt should have modes 644, key - 600
      cert /etc/openvpn/keys/office.crt
      key /etc/openvpn/keys/office.key
      # File with Diffie-Hellman parameters. If you have a different key length, correct the name :)
      dh /etc/openvpn/keys/dh1024.pem
      # Distribute to remote clients the addresses in this subnet, from this range (note - the subnet is set to ALL, as in the network card configuration, and the range is part of the subnet)
      server-bridge 192.168.168.254 255.255.255.0 192.168.168.128 192.168.168.159
      # Allow clients to interact with each other (otherwise only with the server and the network segment "behind the bridge")
      client-to-client
      # This will allow the client to give the same address that was given earlier, if not busy
      ifconfig-pool-persist /etc/openvpn/ipp.txt
      # If you do not want to transfer the DNS server address through DHCP as well, you can remove the following line
      push "dhcp-option DNS 192.168.168.254"
      # Compression
      comp-lzo
      # Maximum number of clients - it makes sense to make less than or equal to the number of addresses in the server-bridge range
      max-clients 32
      # Details on these keys are in the OpenVPN documentation
      keepalive 10 120
      # Do not reinitialize tun or re-read the key when reconnecting; if we work not as root, but as nobody, then they will not allow us to do this, therefore either all of these options, or none of them
      user nobody
      group nobody
      persist-key
      persist-tun
      # Every minute OpenVPN resets the current state here (list of clients, routes, etc.)
      status /tmp/openvpn-status.log
      # Very noisy log, normal operation - verb 2
      verb 6
      log-append /var/log/openvpn.log
    


    The key office.key must have mode 600 (access only to the owner). The files office.crt and dh1024.pem are in 644 mode .

    Filtering settings



    Since we use a bridge, there are several features for organizing packet filtering. For example, not all passing packets may be IPv4 at all. There are several parameters for configuring the operation of the bridge in the kernel: The

    variables of this group are stored in the files of the / proc / sys / net / bridge / directory. They can also be configured in /etc/sysctl.conf, then they will all get the prefix “net.brigde.”
    • bridge-nf-call-arptables The
      logical variable bridge-nf-call-arptables controls the transfer of ARP traffic to the FORWARD chain of the arptables packet filter. The default value of 1 allows the transmission of packets to filters, 0 - prohibits.
    • bridge-nf-call-iptables The
      logical variable bridge-nf-call-iptables controls the transfer of IPv4 traffic passing through the bridge to iptables chains. The default value of 1 allows the transmission of packets for filtering, 0 - prohibits.
    • bridge-nf-call-ip6tables
      The action is similar to the previous one, only it configures the transmission of IPv6 traffic for filtering into ip6tables chains.
    • bridge-nf-filter-vlan-tagged
      boolean variable bridge-nf-filter-vlan-tagged defines the ability to transmit IP / ARP traffic with VLAN tags to packet filtering programs (arptables / iptables). The value 1 (set by default) allows the transmission of packets with VLAN tags to filtering programs, 0 - prohibits.


    To filter packets passing through the bridge, physdev matching is used, which distinguishes between which port and on which bridge the packet goes. Turn it on in the kernel:

    -> Networking
      -> Networking support (NET [= y])
        -> Networking options
          -> Network packet filtering framework (Netfilter) (NETFILTER [= y])
            -> Core Netfilter Configuration
              -> Netfilter Xtables support (required for ip_tables) (NETFILTER_XTABLES [= y])
                -> "physdev" match support (NETFILTER_XT_MATCH_PHYSDEV [= y])
    


    In addition, the kernel configuration should allow the transfer of packets to iptables filtering, i.e. bridge-nf-call-iptables = 1 and bridge-nf-call-ip6tables = 1 (if you are using IPv6).
    After you can use, for example, the following rules for filtering:

      iptables -A FORWARD -p tcp --dport 22 -m physdev --physdev-in eth1 --physdev-out eth0 -j ACCEPT
    

    You can read more about configuring filtering between post ports in the article Building bridges with Linux.

    If you do not want to make any distinction between LAN users and bridged VPN users, you can simply turn off these options in the kernel (they are enabled by default):

      echo "net.bridge.bridge-nf-call-iptables = 0" >> /etc/sysctl.conf
      echo "net.bridge.bridge-nf-call-ip6tables = 0" >> /etc/sysctl.conf
    


    Customers


    On the client, you need to create an OpenVPN configuration file with the following contents:

      client
      nobind
      dev tap
      proto udp
      # Where to connect. You can specify several remote options - the first available server will be used. If there are several A-records for server.example.net, the choice between them is random.
      remote server.example.net 1194
      # Never give up, try to connect endlessly.
      resolv-retry infinite
      # Either all options together, or none of them
      persist-key
      persist-tun
      user nobody
      group nogroup
      comp-lzo
      ns-cert-type server
      ca ca.crt
      cert client.crt
      key client.key
    


    If the server is connected through several providers, you can increase the network resilience to failures. To do this, the client needs to register several remote options, one per server, in the "preferred first" order.

    The file names specified in the ca, cert, and key parameters are the files transferred through the secure channel. Permissions on the key file must be set to 600.

    Linux


    A universal tun / tap driver is required in the kernel, or by a module, but loaded.

    Gentoo

    Installing net-misc / openvpn creates the script /etc/init.d/openvpn. This script starts openvpn with the configuration file /etc/openvpn/openvpn.conf. However, we can support several OpenVPN configurations simultaneously if we make symlinks of the form /etc/init.d/openvpn.network-name -> /etc/init.d/openvpn - each such script launches OpenVPN with the configuration file / etc / openvpn /network-name.conf.

    Accordingly, we put the above config there, create a symlink and put the scripts in a subdirectory in / etc / openvpn /. In the config register the full path to the key and certificates. Make sure that the file names in the config do not overlap, in order to avoid unpleasant effects!

    Starting and stopping the network is done through the management of the /etc/openvpn.network-name service.

    Windows


    The configuration file is placed in the directory “C: \ Program Files \ OpenVPN \ config \” with a name like “office.ovpn”, the rest of the files - keys and certificates are also placed there. If we put them in a subdirectory (for example, we want to use several virtual networks and they all provided files with the same name ca.crt), we indicate the full paths to the files.

    To start the networks, you can either start the OpenVPN service (then all * .ovpn configurations found in config \ will be launched), or individually, right-click on the .ovpn file and select "Run OpenVPN with this configuration."

    Possible problems


    Check the availability of the server, if it is running on TCP, you can use the usual telnet.

    Windows


    No free virtual TAP adapter

    Wed Dec 31 10:43:51 2008 TCP connection established with 88.83.201.253:1194 
    Wed Dec 31 10:43:51 2008 TCPv4_CLIENT link local: [undef] 
    Wed Dec 31 10:43:51 2008 TCPv4_CLIENT link remote: 88.83.201.253:1194 
    Wed Dec 31 10:44:51 2008 TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity) 
    Wed Dec 31 10:44:51 2008 TLS Error: TLS handshake failed 
    Wed Dec 31 10:44:51 2008 Fatal TLS error (check_tls_errors_co), restarting 
    Wed Dec 31 10:44:51 2008 SIGUSR1[soft,tls-error] received, process restarting 
    Wed Dec 31 10:44:56 2008 IMPORTANT: OpenVPN's default port number is now 1194, based on an official port number assignment by IANA.  OpenVPN 2.0-beta16 and earlier used 5000 as the default port. 
    Wed Dec 31 10:44:56 2008 Re-using SSL/TLS context 
    Wed Dec 31 10:44:56 2008 LZO compression initialized 
    Wed Dec 31 10:44:56 2008 Attempting to establish TCP connection with 88.83.201.253:1194 
    Wed Dec 31 10:44:56 2008 TCP connection established with 88.83.201.253:1194 
    Wed Dec 31 10:44:56 2008 TCPv4_CLIENT link local: [undef] 
    Wed Dec 31 10:44:56 2008 TCPv4_CLIENT link remote: 88.83.201.253:1194 
    Wed Dec 31 10:45:11 2008 [office] Peer Connection Initiated with 88.83.201.253:1194 
    Wed Dec 31 10:45:13 2008 All TAP-Win32 adapters on this system are currently in use. 
    Wed Dec 31 10:45:13 2008 Exiting 
    Press any key to continue...
    

    The OpenVPN log shows that the client successfully connected to the server, logged in, but could not bind the virtual network to the virtual adapter. Most likely, some other processes have already affected all TAP-Win32 adapters in the system. It could be OpenVPN itself, hanging and not giving up the adapter.

    It is treated by rebooting or figuring out what kind of processes these might be and forcibly killing them.

    References


    When writing this article, the following sources were used:
    1. Gentoo Linux Wiki - HOWTO OpenVPN Server for Ethenet Bridging with Server Certificates (There is a copy of this page at http://www.gentoo-wiki.info/HOWTO_OpenVPN_Server_for_Ethernet_Bridging_with_Server_Certificates . Thanks hexes for the link!)
    2. Gentoo Linux Wiki - HOWTO OpenVPN Linux Server Windows Client
    3. OpenVPN Documentation - HOWTO
    4. Network Protocol Encyclopedia - sysctl parameters for IP stack
    5. Building bridges with linux


    PS Some sources rested. I will not remove links, but it is worth keeping in mind.

    Also popular now: