[Solved] Route from client to subnet behind other client

This forum is for admins who are looking to build or expand their OpenVPN setup.

Moderators: TinCanTech, TinCanTech, TinCanTech, TinCanTech, TinCanTech, TinCanTech

Forum rules
Please use the [oconf] BB tag for openvpn Configurations. See viewtopic.php?f=30&t=21589 for an example.
Locked
tspf
OpenVpn Newbie
Posts: 13
Joined: Tue Jan 07, 2014 8:15 am

[Solved] Route from client to subnet behind other client

Post by tspf » Tue Jan 07, 2014 3:02 pm

Hello Forum,

my first post here and maybe someone can give me a little advise. I have a little knowledge and have installed a few openvpn-servers. There was always the requirement to access resources on the server side from the client. That worked just fine.

Now the requirement is to reach a subnet behind a client from another client of the vpn-network.


I have a running configuration which is as follows:

Configuration of the server:
/etc/openvpn/server.conf

Code: Select all

port 1194
proto udp
dev tun0
mode server
tls-server
topology subnet
server 10.0.0.0 255.255.255.0
client-to-client
client-config-dir /etc/openvpn/client-config
keepalive 10 120
comp-lzo
up /etc/openvpn/up-cmd
down /etc/openvpn/down-cmd
learn-address /etc/openvpn/learn-address-cmd
client-connect /etc/openvpn/client-connect-cmd
client-disconnect /etc/openvpn/client-disconnect-cmd
dh /etc/openvpn/rsa/keys/dh1024.pem
ca /etc/openvpn/rsa/keys/ca.crt
cert /etc/openvpn/rsa/keys/ovpn-server.crt
key /etc/openvpn/rsa/keys/ovpn-server.key
crl-verify /etc/openvpn/rsa/keys/crl.pem
cipher AES-256-CBC
script-security 2
log /var/log/ovpn-mpaconcentrator.log
verb 6
Client-config files on the server /etc/openvpn/client-config/ :
/etc/openvpn/client-config/linux-client

Code: Select all

iroute 172.16.0.0 255.255.255.0
/etc/openvpn/client-config/windows-client

Code: Select all

push "route 172.16.0.0 255.255.255.0"
Configuration of the windows-client:

Code: Select all

client
remote x.x.x.x
dev tun
port 1194
tls-client
keepalive 10 120
nobind
pull
comp-lzo
verb 6
cipher aes-256-cbc
<ca>
 # ca-cert
</ca>

<cert>
 # certificate
</cert>

<key>
 # private key
</key>
Configuration of the linux-client:

Code: Select all

client
remote x.x.x.x
dev tun
port 1194
tls-client
keepalive 10 120
nobind
pull
comp-lzo
verb 6
cipher aes-256-cbc
ca /etc/openvpn/ca.crt
cert /etc/openvpn/linux-client.crt
key /etc/openvpn/linux-client.key

A little drawing to give you an overview:

Code: Select all

                        
*windows-client* <---------> *ovpn-server* <--------> *linux-client* <-------> *network-devices* 172.16.0.0 /24
VPN-IP: 10.0.0.3             VPN-IP: 10.0.0.1         VPN-IP: 10.0.0.2                                      
Routing-table:                                                (ip-forwarding enabled)
172.16.0.0 /24 via 10.0.0.1      


I am able to ping a client in the 172.16.0.0 /24 subnet from the windows-client. So internal routing of openvpn seems to work.

My first problem is the following:
Because I only want to allow communications over certain ports between the openvpn-clients I need to be able to filter all traffic between the windows-client and the linux-client with iptables.
But at the moment all traffic goes directly from the linux-client to the windows-client because i used the "client-to-client" directive in the server configuration file.
Is it possible to do the routing "outside" of the openvpn process on the ovpn-server?
That would allow me to do things like policy based routing and so on. For example i could route all traffic from a specific source to a specific vpn-client (no more need for the "iroute" stuff!)

Second problem is: In the future there will be more linux-clients with the same subnets attached to them (more details in the ascii drawing). This is because the "network-devices" behind the linux-client are preconfigured industrial machines. They almost always use the same ip-address ranges and i am not allowed to change these.

My thought was as follows:
Create a routing-table entry on a windows-client like this:
/etc/openvpn/client-config/windows-client

Code: Select all

push "route 172.16.0.0 255.255.255.0 10.0.0.2"
/etc/openvpn/client-config/another-windows-client

Code: Select all

push "route 172.16.0.0 255.255.255.0 10.0.0.6"
So i try to use the open-vpn-client as my gateway. But that does not work and i do not know why.

Code: Select all

*windows-client* ------------------            -------------*linux-client* <-------> *network-devices* 172.16.0.0 /24
VPN-IP: 10.0.0.3                  |           |              VPN-IP: 10.0.0.2
Routing-table:                    |           |              (ip-forwarding enabled)
172.16.0.0 /24 via 10.0.0.2       |           |
                                  |           |
                                  |           |
                                 *ovpn-server  VPN-IP: 10.0.0.1 *
                                   |             |
                                   |             |
                                   |             |
*another-windows-client* -----------              ------------*another-linux-client* <-------> *network-devices* 172.16.0.0 /24
VPN-IP: 10.0.0.3                                                      VPN-IP: 10.0.0.6
Routing-table:                                                        (ip-forwarding enabled)
172.16.0.0 /24 via 10.0.0.6                                                                                        
So i defined a route to a subnet behind a specific openvpn-client (10.0.0.2 or 10.0.0.6). This openvpn-client is my gateway. But the packet never reaches the openvpn-client and i do not know why.
I was not able to send any packet to a subnet behind a openvpn-client with this way.

What am I doing wrong?
Is there an alternative method for my goal?

Do you need any more information?
Last edited by debbie10t on Thu Feb 13, 2014 4:24 pm, edited 1 time in total.
Reason: [Solved / closed]

tspf
OpenVpn Newbie
Posts: 13
Joined: Tue Jan 07, 2014 8:15 am

Re: Route traffic from client to subnet behind another clien

Post by tspf » Sat Feb 01, 2014 9:44 am

It seems that i've found a solution that works for me.

I still have to use iroute , there seems to be no way to handle the routing entirely in the kernel of the linux-os.

I changed my setup to the following:

This tells the openvpn-server that the linux-client is responsible for the network 192.168.23.0/24
and will route all incoming traffic inside the openvpn-process to this linux-client.
/etc/openvpn/client-config/linux-client:

Code: Select all

iroute 192.168.23.0 255.255.255.0

This tells the windows-client to route all traffic for the 192.168.23.0/24 subnet to the openvpn-server.
/etc/openvpn/client-config/windows-client

Code: Select all

push "route 192.168.23.0 255.255.255.0"
My idea is to use a network of "unused" addresses to NAT the subnets behind the linux-client(s).
Because there could be more than one subnet with the same addressspace.

If i want to reach a machine in the 172.16.0.0 /24 network behind the linux-client, on the windows-client side i use a "fake" network
of 192.168.23.0 /24 or 192.168.24.0/24 or anything else which is not used in the entire intranet (it should of course be a "private" network).

So in this example, to reach 172.16.0.14 /24 behind the linux-client a route will be set on the windows-client which tells him to reach 192.168.23.14/24 via the openvpn-server address.

The packet with the destination address 192.168.23.14 now gets send to the openvpn-server, "exits" the tun0 interface and enters the kernel routing table. So we have to tell the server what to do with the packet. We tell him that everything for 192.168.23.14 /24 gets routed to the tun0 address, in my case 10.0.0.1.

Code: Select all

ip route add to 192.168.23.0/24 via 10.0.0.1
The packet now traverses the openvpn-server and enters the tun0 interface again, so that the openvpn-process takes over. Because we told openvpn with the iroute statement that the linux-client is responsible for this "fake" network it will route the packet to the openvpn-address (10.0.0.3 in my case) of the linux-client.

The linux client itself must know that it has to alter the incoming packets with destination address 192.168.23.14/24 to 172.16.0.14/24. This is done with iptables rules like this:

Code: Select all

iptables -t nat -A PREROUTING -i tun0 -s -d 192.168.23.14 -j DNAT --to-destination 172.16.0.14
iptables -t nat -A POSTROUTING -o eth1 -s -d 172.16.0.14 -j MASQUERADE
We tell the kernel netfilter module to replace the destination ip-address of every incoming packet from tun0 with the destination-ip 192.168.23.14 to the new destination-ip 172.16.0.14.
After that the source address of the packet is also exchanged and the address of the local interface, which is connected to the 172.16.0.0/24 network, is added.

So the packet first looks like this:

Code: Select all

Source-IP: 10.0.0.2
Destination-IP: 192.168.23.14
And after the alteration with iptables it looks like this:

Code: Select all

Source-IP: 172.16.0.5 (the ip-address of the local interface of the linux-client in the 172.16.0.0/24 network)
Destination-IP: 172.16.0.14 (the ip-address of the client in the target network which i want to reach)
Because of the MASQUERADE functionality iptables is able to modify the packets which now will be send back from the target machine 172.16.0.14 again.

Initially the answering packet looks like:

Code: Select all

Source-IP: 172.16.0.14 (ip-address of the client in the target network)
Destination-IP: 172.16.0.5 (ip-address of the linux client which does the NAT)
Now the MASQUERADE is doing its magic and alters the packet like this:

Code: Select all

Source-IP: 192.168.23.14 (the fake ip-address to which the windows client sends its packets)
Destination-IP: 10.0.0.2 (the open-vpn address of the windows client)
The downside is the effort in setting this up. Because you have to create a "mapping table" to know which "fake ip" is responsible for which "real ip" behind which client, but in my case it is worth the effort.

Maybe this solution helps somebody else.

Locked