OpenWrt sends ICMP redirect with wrong(?) IP address for OpenVPN TUN Interface

Add it to the server config, it is supported since OpenVPN 2.1.
Set netmask to 255.255.255.0, and also if you use ccd, replace peer address with netmask.


And make sure:

  1. Forwarding is enabled on R1 and S1.
  2. Firewall on R1 and S1 allows transit traffic between LAN and VPN.
  3. S1 and U1 have route to D1.
  4. R1 is default gateway for D1.

I have set the "topology subnet" option now, since I have no such old clients running.

The routes and firewall rules are ok in general, because I am able to ping from U1 to PC1 which is in the same subnet as D1.

Same thing now again (10.1.139.90 = D1).
First ping works, then the ICMP redirect -> ping stops.

R1:

tun1      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet addr:10.102.0.30  P-t-P:10.102.0.30  Mask:255.255.0.0
          inet6 addr: fe80::d57d:5783:9481:ef4d/64 Scope:Link
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:141 errors:0 dropped:0 overruns:0 frame:0
          TX packets:172 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:10664 (10.4 KiB)  TX bytes:14334 (13.9 KiB)

r1:~# tcpdump -nni br-lan icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br-lan, link-type EN10MB (Ethernet), capture size 262144 bytes
18:40:03.120597 IP 10.102.0.23 > 10.1.139.90: ICMP echo request, id 1, seq 1901, length 40
18:40:03.121399 IP 10.1.139.90 > 10.102.0.23: ICMP echo reply, id 1, seq 1901, length 40
18:40:03.133794 IP 10.102.0.1 > 10.1.139.90: ICMP redirect 10.102.0.23 to host 10.102.0.23, length 68
18:40:04.126161 IP 10.102.0.23 > 10.1.139.90: ICMP echo request, id 1, seq 1902, length 40
18:45:39.984568 IP 10.102.0.23 > 10.1.139.90: ICMP echo request, id 1, seq 1903, length 40
18:45:44.958939 IP 10.102.0.23 > 10.1.139.90: ICMP echo request, id 1, seq 1904, length 40
18:45:50.812549 IP 10.102.0.23 > 10.1.139.90: ICMP echo request, id 1, seq 1905, length 40

I have also PLC1 on in this network which I can ping (just updated the main post).

There is a different behavior on a ping to PC1 (10.1.139.50) vs. PLC1 (10.1.139.1):

r1:~# tcpdump -nni br-lan icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br-lan, link-type EN10MB (Ethernet), capture size 262144 bytes
19:00:57.485361 IP 10.102.0.23 > 10.1.139.50: ICMP echo request, id 1, seq 1913, length 40
19:00:57.486102 IP 10.1.139.50 > 10.102.0.23: ICMP echo reply, id 1, seq 1913, length 40
19:00:58.549607 IP 10.102.0.23 > 10.1.139.50: ICMP echo request, id 1, seq 1914, length 40
19:00:58.549879 IP 10.1.139.50 > 10.102.0.23: ICMP echo reply, id 1, seq 1914, length 40
19:00:59.510747 IP 10.102.0.23 > 10.1.139.50: ICMP echo request, id 1, seq 1915, length 40
19:00:59.511660 IP 10.1.139.50 > 10.102.0.23: ICMP echo reply, id 1, seq 1915, length 40

19:01:08.630666 IP 10.102.0.23 > 10.1.139.1: ICMP echo request, id 1, seq 1916, length 40
19:01:08.631077 IP 10.1.139.1 > 10.102.0.23: ICMP echo reply, id 1, seq 1916, length 40
19:01:08.644305 IP 10.102.0.1 > 10.1.139.1: ICMP redirect 10.102.0.23 to host 10.102.0.23, length 68
19:01:09.635438 IP 10.102.0.23 > 10.1.139.1: ICMP echo request, id 1, seq 1917, length 40
19:01:09.635688 IP 10.1.139.1 > 10.102.0.23: ICMP echo reply, id 1, seq 1917, length 40
19:01:09.647856 IP 10.102.0.1 > 10.1.139.1: ICMP redirect 10.102.0.23 to host 10.102.0.23, length 68
19:01:10.640671 IP 10.102.0.23 > 10.1.139.1: ICMP echo request, id 1, seq 1918, length 40
19:01:10.640910 IP 10.1.139.1 > 10.102.0.23: ICMP echo reply, id 1, seq 1918, length 40
19:01:10.652880 IP 10.102.0.1 > 10.1.139.1: ICMP redirect 10.102.0.23 to host 10.102.0.23, length 68

How can the router send a redirect to a non Layer2 device?

Did you bridge to a VLAN?

Your VPN-interface still looks somewhat fishy, it should be like this:

# ip -4 a sh dev tun0
14: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN qlen 100
    inet 192.168.8.1/24 brd 192.168.8.255 scope global tun0
       valid_lft forever preferred_lft forever

It seems you have redundant masquerading on VPN-interfaces - remove it.
Using routes should be enough.
Also make sure you have iroute for D1-LAN on R1.

So far as I understand is an ICMP redirect only required, if there is another router on the LAN which has a better router to the destination.
https://www.cisco.com/c/en/us/support/docs/ip/routing-information-protocol-rip/13714-43.html

I am wondering why the OpenWrt router is sending these ICMP redirects with 10.102.0.23 as gateway.
10.102.0.23 is right now actually the OpenVPN TUN Adapter on U1 (Windows 10 PC running OpenVPN client).

R1:

r1:~# ip -4 a sh dev tun1
12: tun1: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN qlen 100
    inet 10.102.0.30/16 brd 10.102.255.255 scope global tun1
       valid_lft forever preferred_lft forever

Masquerading is only active on the WAN interface.
The routes get pushed from S1 to R1 and they are working fine since I can reach PC1 and PLC1 without any problems.

Could you show from R1 and S1:

ip -4 a; ip -4 r

?

Sure, here we go.

R1:

r1:~# ip -4 a; ip -4 r
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
6: br-lan: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    inet 10.1.139.254/24 brd 10.1.139.255 scope global br-lan
       valid_lft forever preferred_lft forever
8: eth0.2@eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
    inet 192.168.0.100/24 brd 192.168.0.255 scope global eth0.2
       valid_lft forever preferred_lft forever
10: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN qlen 100
    inet 10.100.139.1 peer 10.100.139.2/32 scope global tun0
       valid_lft forever preferred_lft forever
12: tun1: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN qlen 100
    inet 10.102.0.30/16 brd 10.102.255.255 scope global tun1
       valid_lft forever preferred_lft forever
default via 192.168.0.254 dev eth0.2  src 192.168.0.100
10.1.0.0/16 via 10.102.0.1 dev tun1
10.1.139.0/24 dev br-lan scope link  src 10.1.139.254
10.100.0.0/16 via 10.102.0.1 dev tun1
10.100.139.0/24 via 10.100.139.2 dev tun0
10.100.139.2 dev tun0 scope link  src 10.100.139.1
10.101.0.0/16 via 10.102.0.1 dev tun1
10.102.0.0/16 via 10.102.0.1 dev tun1
10.102.0.0/16 dev tun1 scope link  src 10.102.0.30
192.168.0.0/24 dev eth0.2 scope link  src 192.168.0.100

S1:
(I only replaced the public IP addresses with x.x.x.x)

s1:~# ip -4 a; ip -4 r
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet x.x.x.x/24 brd x.x.x.255 scope global eth0
       valid_lft forever preferred_lft forever
3: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
    inet 10.101.0.1 peer 10.101.0.2/32 scope global tun0
       valid_lft forever preferred_lft forever
4: tun1: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
    inet 10.102.0.1/16 brd 10.102.255.255 scope global tun1
       valid_lft forever preferred_lft forever
default via x.x.x.x dev eth0
10.1.2.0/24 dev tun0  scope link
10.1.3.0/24 dev tun0  scope link
10.1.4.0/24 dev tun0  scope link
10.1.5.0/24 dev tun1  scope link
10.1.6.0/24 dev tun1  scope link
10.1.7.0/24 dev tun1  scope link
10.1.9.0/24 dev tun0  scope link
10.1.11.0/24 dev tun1  scope link
10.1.12.0/24 dev tun1  scope link
10.1.13.0/24 dev tun0  scope link
10.1.14.0/24 dev tun0  scope link
10.1.17.0/24 dev tun0  scope link
10.1.20.0/24 dev tun1  scope link
10.1.24.0/24 dev tun1  scope link
10.1.25.0/24 dev tun0  scope link
10.1.26.0/24 dev tun0  scope link
10.1.27.0/24 dev tun0  scope link
10.1.30.0/24 dev tun0  scope link
10.1.31.0/24 dev tun0  scope link
10.1.33.0/24 dev tun1  scope link
10.1.34.0/24 dev tun0  scope link
10.1.35.0/24 dev tun1  scope link
10.1.38.0/24 dev tun0  scope link
10.1.39.0/24 dev tun0  scope link
10.1.41.0/24 dev tun1  scope link
10.1.42.0/24 dev tun0  scope link
10.1.44.0/24 dev tun1  scope link
10.1.51.0/24 dev tun0  scope link
10.1.52.0/24 dev tun1  scope link
10.1.53.0/24 dev tun0  scope link
10.1.54.0/24 dev tun0  scope link
10.1.56.0/24 dev tun1  scope link
10.1.60.0/24 dev tun0  scope link
10.1.61.0/24 dev tun1  scope link
10.1.63.0/24 dev tun0  scope link
10.1.64.0/24 dev tun0  scope link
10.1.66.0/24 dev tun0  scope link
10.1.67.0/24 dev tun0  scope link
10.1.69.0/24 dev tun0  scope link
10.1.70.0/24 dev tun0  scope link
10.1.71.0/24 dev tun1  scope link
10.1.76.0/24 dev tun1  scope link
10.1.77.0/24 dev tun1  scope link
10.1.78.0/24 dev tun1  scope link
10.1.79.0/24 dev tun0  scope link
10.1.80.0/24 dev tun1  scope link
10.1.81.0/24 dev tun0  scope link
10.1.82.0/24 dev tun1  scope link
10.1.84.0/24 dev tun0  scope link
10.1.86.0/24 dev tun0  scope link
10.1.87.0/24 dev tun0  scope link
10.1.88.50 dev tun1  scope link
10.1.89.0/24 dev tun0  scope link
10.1.90.0/24 dev tun1  scope link
10.1.91.0/24 dev tun0  scope link
10.1.92.0/24 dev tun1  scope link
10.1.93.0/24 dev tun0  scope link
10.1.95.0/24 dev tun1  scope link
10.1.96.0/24 dev tun0  scope link
10.1.97.0/24 dev tun1  scope link
10.1.98.0/24 dev tun1  scope link
10.1.99.0/24 dev tun0  scope link
10.1.100.50 dev tun0  scope link
10.1.101.0/24 dev tun0  scope link
10.1.102.0/24 dev tun0  scope link
10.1.103.0/24 dev tun0  scope link
10.1.105.0/24 dev tun0  scope link
10.1.107.0/24 dev tun0  scope link
10.1.108.0/24 dev tun1  scope link
10.1.109.0/24 dev tun0  scope link
10.1.111.0/24 dev tun0  scope link
10.1.112.0/24 dev tun1  scope link
10.1.113.0/24 dev tun0  scope link
10.1.114.0/24 dev tun0  scope link
10.1.115.50 dev tun1  scope link
10.1.116.0/24 dev tun1  scope link
10.1.118.0/24 dev tun1  scope link
10.1.119.0/24 dev tun0  scope link
10.1.120.0/24 dev tun0  scope link
10.1.121.50 dev tun0  scope link
10.1.122.0/24 dev tun0  scope link
10.1.123.0/24 dev tun0  scope link
10.1.124.0/24 dev tun0  scope link
10.1.125.0/24 dev tun1  scope link
10.1.126.0/24 dev tun0  scope link
10.1.128.50 dev tun1  scope link
10.1.129.0/24 dev tun1  scope link
10.1.132.0/24 dev tun1  scope link
10.1.133.0/24 dev tun1  scope link
10.1.135.0/24 dev tun1  scope link
10.1.136.50 dev tun1  scope link
10.1.137.0/24 dev tun1  scope link
10.1.139.0/24 dev tun1  scope link
10.1.141.50 dev tun1  scope link
10.1.142.50 dev tun1  scope link
10.1.143.0/24 dev tun1  scope link
10.1.145.0/24 dev tun1  scope link
10.1.146.0/24 dev tun1  scope link
10.1.149.0/29 dev tun1  scope link
10.1.153.0/24 dev tun1  scope link
10.100.9.0/24 dev tun0  scope link
10.100.35.0/24 dev tun1  scope link
10.100.60.0/24 dev tun0  scope link
10.100.76.0/24 dev tun1  scope link
10.101.0.0/16 via 10.101.0.2 dev tun0
10.101.0.2 dev tun0  proto kernel  scope link  src 10.101.0.1
10.102.0.0/16 dev tun1  proto kernel  scope link  src 10.102.0.1
x.x.x.0/24 dev eth0  proto kernel  scope link  src x.x.x.x
192.168.0.0/20 dev tun1  scope link

I added a firewall rule on R1 to prevent sending out ICMP requests, but event this does not help.

config rule
        option enabled '1'
        option name 'ICMP redirect disable'
        option family 'ipv4'
        option proto 'icmp'
        option icmp_type 'redirect'
        option src '*'
        option dest '*'
        option target 'REJECT'

Still the same thing, first ping works -> ICMP redirect -> ping stops

r1:~# tcpdump -nni br-lan icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br-lan, link-type EN10MB (Ethernet), capture size 262144 bytes
19:52:15.210343 IP 10.102.0.23 > 10.1.139.90: ICMP echo request, id 1, seq 1947, length 40
19:52:15.210963 IP 10.1.139.90 > 10.102.0.23: ICMP echo reply, id 1, seq 1947, length 40
19:52:15.222545 IP 10.102.0.1 > 10.1.139.90: ICMP redirect 10.102.0.23 to host 10.102.0.23, length 68
19:52:16.198061 IP 10.102.0.23 > 10.1.139.90: ICMP echo request, id 1, seq 1948, length 40
19:52:20.967945 IP 10.102.0.23 > 10.1.139.90: ICMP echo request, id 1, seq 1949, length 40

Should not at least this firewall rule prevent the router to send out these ICMP redirects?

Should not the line
"ACCEPT all -- anywhere anywhere /* !fw3 */"
be at the end of the chain OUTPUT and not at the beginn?

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             /* !fw3 */
output_rule  all  --  anywhere             anywhere             /* !fw3: Custom output rule chain */
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED /* !fw3 */
zone_lan_output  all  --  anywhere             anywhere             /* !fw3 */
zone_wan_output  all  --  anywhere             anywhere             /* !fw3 */
zone_wan_output  all  --  anywhere             anywhere             /* !fw3 */
zone_wan_output  all  --  anywhere             anywhere             /* !fw3 */
zone_VPN_output  all  --  anywhere             anywhere             /* !fw3 */
zone_VPN_output  all  --  anywhere             anywhere             /* !fw3 */

Chain zone_lan_output (1 references)
target     prot opt source               destination
output_lan_rule  all  --  anywhere             anywhere             /* !fw3: Custom lan output rule chain */
zone_lan_dest_DROP  icmp --  anywhere             anywhere             icmp redirect /* !fw3: ICMP redirect disable */
zone_lan_dest_ACCEPT  all  --  anywhere             anywhere             /* !fw3 */

Chain zone_lan_dest_DROP (1 references)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere             /* !fw3 */

/etc/config/firewall

config defaults
        option output 'ACCEPT'

This helped now to prevent the router sending out these ICMP redirects and the ping to D1 is working fine.

iptables -I FORWARD -p icmp --icmp-type redirect -j DROP

Not sure if this behavior of the OpenWrt firewall is correct.
I opened there a seperate thread for it.

However, I am still wondering why it sends out these weird ICMP redirects in general.
That I had to add the DROP to the FORWARD table means to me that these ICMP redirects are maybe not generated by the OpenWRT system, otherwise the OUTPUT table would have worked.

Where else could it come from?

It is originated from S1 (10.102.0.1):

S1 thinks that 10.102.0.23 is reachable directly from 10.1.139.90.
And network 10.1.139.0/24 is considered by S1 as reachable locally, not remotely.
And this is the reason:


Correct route should be like this:

10.1.139.0/24 via 10.102.0.30 dev tun1

To create it automatically by VPN-server:

# server.conf
route 10.1.139.0/24 255.255.255.0

# ccd/R1
ifconfig-push 10.102.0.30 255.255.255.0
iroute 10.1.139.0 255.255.255.0

I have to explain my setup here more in detail, because it is more complex.

There are two OpenVPN server processes (10.101.0.1 & 10.102.0.1) running on S1 with different ports.
The clients can connect to both of them.

There is a LDAP server running which provides the authentication information for each client. This gets handled by the openvpn-auth-ldap plugin.

The LDAP server also provides the IP range information for each client as well as some permission rules for clients for the iptables settings. This gets handled by a perl script.

The scripts generates the following config file for the OpenVPN client on R1.

iroute 10.1.139.0 255.255.255.0
push "route 10.1.0.0 255.255.0.0"
push "route 10.100.0.0 255.255.0.0"
push "route 10.101.0.0 255.255.0.0"
push "route 10.102.0.0 255.255.0.0"

I cannot add

route 10.1.139.0/24

to the server config file, because I don't know to which server the client will connect and there also will be another IP address range if someone adds a new client to the LDAP server.

I also cannot add

route 10.1.0.0 255.255.0.0

to the server, because I would have to add it to both servers what probably would not work.
So far as I have seen is this route option not available for the ccd, so I cannot assign it dynamically with the script to the according server.

Any ideas how to get around this issue?

https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage

--client-connect cmd
--client-disconnect cmd
The command is passed the common name and IP address of the just-authenticated client as environmental variables (see environmental variable section below). The command is also passed the pathname of a freshly created temporary file as the last argument (after any arguments specified in cmd ), to be used by the command to pass dynamically generated config file directives back to OpenVPN.

Right, I already use these environmental variables for my script which fills the options into this temporary file.

client_connect.sh:

#!/bin/bash
exec sudo /etc/openvpn/scripts/openvpn.pl client-connect $username $ifconfig_pool_remote_ip $1 $trusted_ip $trusted_port $dev

So far as I understand is this temporary file the same as a config file in a ccd and for that I cannot use route option.

I assume that client LAN (remote_network) is extracted from LDAP by openvpn.pl.
And openvpn.pl also creates all those incorrect routes with scope link.
So you need to fix that command to look like this:

ip route {add|del} $remote_network via $ifconfig_pool_remote_ip dev $dev

Right, this fixed my issue, you are good man!

I generated something like this with the script before:

route add -net 10.1.139.0 netmask 255.255.255.0 dev tun1

Now I have changed it like you advised:

route add -net 10.1.139.0 netmask 255.255.255.0 gw 10.102.0.22 dev tun1

This is how it looked before:

10.1.139.0/24 dev tun1 scope link

And now:

10.1.139.0/24 via 10.102.0.22 dev tun1

Thank you very much for your extensive help!

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.