It’s pretty easy in FreeBSD to create simple tunnels between two FreeBSD machines, between a FreeBSD machine and a Cisco router, or to any other host that supports the GRE interface.
The GRE (Generic Routing Encapsulation) interface (defined in RFC 1701 and 1702) has been included for a while, and provides a “standard” encapsulation protocol for tunneling.
So lets assume first a host-to-host tunnel:
External IP: 192.168.10.1 Tunnel IP: 10.255.255.1/30 Internal Block: 10.10.0.1/24
External IP: 192.168.20.1 Tunnel IP: 10.255.255.2/30 Internal Block: 10.20.0.1/24
Obviously, in a real-world situation, the “External IP” value in your setup, would likely be a real, valid, routable IP address. Also, I like to use a “stub” host block for the tunnel IP addresses- this is basically a block of four IP’s (/30, 2 usable), that are simply used to route either end of the tunnel.
Yes, you can use an IP in the internal block as the tunnel interface, which means you wouldn’t need the extra routes to route the local blocks, but this can break OSPF, so it’s just good (maybe?) practice to keep the two blocks separate.
First off, you need to make sure the gre interface type is available; your kernel should be compiled with:
or, if you’ve built all the modules as loadable, you can add:
to your /boot/loader.conf; you can then either reboot, or run:
host> /sbin/kldload /boot/kernel/if_gre.ko
Which should load the module.
Next, you need to configure the interfaces on both machines; this assumes you don’t already have a greN interface setup- if you do, then just use the next logical number instead of 0.
On Host A:
ifconfig gre0 create ifconfig gre0 10.255.255.1 10.255.255.2 netmask 255.255.255.252 ifconfig gre0 tunnel 192.168.10.1 192.168.20.1
On Host B:
ifconfig gre0 create ifconfig gre0 10.255.255.2 10.255.255.1 netmask 255.255.255.252 ifconfig gre0 tunnel 192.168.20.1 192.168.10.1
You can run ifconfig gre0 on each host, and the interface should show as UP. You can also confirm it’s up by pinging the other end of the tunnel from each host; so from Host A, ping the 10.255.255.2 IP address (which is the remote end of the tunnel):
hosta> ping -c 3 10.255.255.2 64 bytes from 10.255.255.2: icmp_seq=0 ttl=64 time=43.192 ms 64 bytes from 10.255.255.2: icmp_seq=1 ttl=64 time=51.099 ms 64 bytes from 10.255.255.2: icmp_seq=2 ttl=64 time=51.459 ms --- 10.255.255.2 ping statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 43.192/48.583/51.459/3.815 ms
Now you need to add routes for your internal blocks, so each end know to route over the tunnel:
On Host A:
route add 10.20.0.1/24 10.255.255.2
On Host B:
route add 10.10.0.1/24 10.255.255.1
Now don’t forget to add this config to your rc.conf files, so the interfaces get setup when the machines reboot:
On Host A:
cloned_interfaces="gre0" ifconfig_gre0="inet 10.255.255.1 10.255.255.2 netmask 255.255.255.252 tunnel 192.168.10.1 192.168.20.1" static_routes="tunnel" route_tunnel="10.20.0.1/24 10.255.255.2"
On Host B:
cloned_interfaces="gre0" ifconfig_gre0="inet 10.255.255.2 10.255.255.1 netmask 255.255.255.252 tunnel 192.168.20.1 192.168.10.1" static_routes="tunnel" route_tunnel="10.10.0.1/24 10.255.255.1"
(the ifconfig line was broken for display purposes; it should be one long line in you rc.conf file)
Now if your Host B in this scenario is not a FreeBSD box, but a Cisco device, the Cisco setup goes like this:
interface Tunnel0 ip address 10.255.255.2 255.255.252 tunnel mode gre tunnel source 192.168.20.1 tunnel destination 192.168.10.1 ! ip route 10.10.0.1/24 255.255.255.0 10.255.255.2
Remember, this is just a simple encapsulation protocol, and not encryption- so data is not secure. Later, I’ll do an update which includes IPSEC on top of the GRE interface.
Great howto, but i cannot ping other hosts internal network ips for some reason, only the internal ip the host we setup the tunnel with, do we need NAT or something?
Well- its’ going to depend on your network setup- there can be a lot of reasons why you can’t ping other hosts;
are the hosts you’re trying to ping on the same network block?
are you able to ping the remote end of the tunnel? in my example, that would be the 10.255.255.2 address.
do you have a firewall or any filtering setup on any of the hosts involved that might be blocking the traffic?
it’s tough to say without more details on your setup.
Simple, clear, thank you !
sysctl router/gateway (dont remember exactly) has to be enabled on both freebsd boxes to get an ability to see other hosts in virtual network
so static routes are not enough