Hi, by accident I discovered this rather senseless redirect:
$ doas tcpdump -eptni vlan2 icmp
tcpdump: listening on vlan2, link-type EN10MB
11:11:11:11:11:11 22:22:22:22:22 0800 98: 192.168.1.2 > 192.168.4.7: icmp: echo
request
22:22:22:22:22 11:11:11:11:11:11 0800 98: 192.168.4.7 > 192.168.1.2: icmp: echo
reply
11:11:11:11:11:11 22:22:22:22:22 0800 70: 192.168.4.1 > 192.168.4.7: icmp:
redirect 192.168.1.2 to host 192.168.4.1
^C
110 packets received by filter
0 packets dropped by kernel
The routing table on 192.168.4.1 tells you why this redirect was sent.
Have a look at the second last route.
% doas ifconfig vlan2
vlan2: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
lladdr 11:11:11:11:11:11
index 7 priority 0 llprio 3
encap: vnetid 2 parent em2
status: active
inet 192.168.4.1 netmask 0xfffffff0 broadcast 192.168.4.15
% doas route -n show -inet
Routing tables
Internet:
Destination Gateway Flags Refs Use Mtu Prio Iface
default 62.27.93.143 UGS 5 63324 - 8 pppoe0
224/4 127.0.0.1 URS 0 0 32768 8 lo0
62.27.93.143 85.212.225.8 UHh 1 1 - 8 pppoe0
85.212.225.8 85.212.225.8 UHl 0 1589 - 1 pppoe0
127/8 127.0.0.1 UGRS 0 0 32768 8 lo0
127.0.0.1 127.0.0.1 UHhl 9 1131 32768 1 lo0
192.168.0/22 192.168.4.1 UGS 0 314 - 8 vlan2
<- this is the culprit
192.168.4.0/28 192.168.4.1 UCn 2 0 - 4 vlan2
Network 192.268.0/22 is remote and connected via IPsec:
$ ipsecctl -s flow
flow esp in from 192.168.0.0/22 to 192.168.4.0/24 type use
flow esp out from 192.168.224.0/24 to 192.168.0.0/17 type require
You'll note I manually (Flag S) added this rather senseless route to gateway
192.268.4.1 (Flag G), which is the very same machine.
Why did I do this?
To prevent leakage of packets which should be routed via IPsec. Without this
pseudo-route packets from localhost to 192.168.0/22 would be routed via default
route on pppoe0 and have a src IP of 85.212.225.8,
which would not be caught by the IPsec flow.
If I'm doing something wrong here and should have solved this an another way
please tell me.
Using a "flow esp in from 0.0.0.0/0" would work on the local side, but the
remote side would be required to accept packets from arbitrary IPs, too.
In any case I'd propose the following diff which will check whether the
redirect target is an address of the interface the forwarded packet came in on.
Christopher
Index: ip_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.322
diff -u -p -r1.322 ip_input.c
--- ip_input.c 7 Sep 2017 10:54:49 -0000 1.322
+++ ip_input.c 1 Dec 2017 18:00:53 -0000
@@ -1514,16 +1514,27 @@ ip_forward(struct mbuf *m, struct ifnet
(rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
satosin(rt_key(rt))->sin_addr.s_addr != 0 &&
ipsendredirects && !srcrt &&
- !arpproxy(satosin(rt_key(rt))->sin_addr, m->m_pkthdr.ph_rtableid)) {
- if ((ip->ip_src.s_addr & ifatoia(rt->rt_ifa)->ia_netmask) ==
- ifatoia(rt->rt_ifa)->ia_net) {
- if (rt->rt_flags & RTF_GATEWAY)
+ !arpproxy(satosin(rt_key(rt))->sin_addr, m->m_pkthdr.ph_rtableid) &&
+ (ip->ip_src.s_addr & ifatoia(rt->rt_ifa)->ia_netmask) ==
+ ifatoia(rt->rt_ifa)->ia_net) {
+ struct ifaddr *ifa;
+
+ if (rt->rt_flags & RTF_GATEWAY)
dest = satosin(rt->rt_gateway)->sin_addr.s_addr;
- else
+ else
dest = ip->ip_dst.s_addr;
- /* Router requirements says to only send host redirects */
- type = ICMP_REDIRECT;
- code = ICMP_REDIRECT_HOST;
+
+ /* don't redirect to the interface the packet came in on. */
+ TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
+ if (ifa->ifa_addr->sa_family == AF_INET &&
+ satosin(ifa->ifa_addr)->sin_addr.s_addr == dest)
+ dest = 0;
+ }
+
+ /* Router requirements says to only send host redirects */
+ if (dest != 0) {
+ type = ICMP_REDIRECT;
+ code = ICMP_REDIRECT_HOST;
}
}
--
http://gmerlin.de
OpenPGP: http://gmerlin.de/christopher.pub
2779 7F73 44FD 0736 B67A C410 69EC 7922 34B4 2566
pgpJ6ZS6cu6bn.pgp
Description: OpenPGP digital signature
