Remove the IPFIREWALL_FORWARD kernel option and make possible to turn

on the related functionality in the runtime via the sysctl variable
net.pfil.forward. It is turned off by default.

Sponsored by:	Yandex LLC
Discussed with:	net@
MFC after:	2 weeks
This commit is contained in:
Andrey V. Elsukov 2012-10-25 09:39:14 +00:00
parent 1da7bb41ed
commit c1de64a495
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=242079
18 changed files with 52 additions and 98 deletions

View File

@ -1,7 +1,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd July 16, 2012
.Dd October 25, 2012
.Dt IPFW 8
.Os
.Sh NAME
@ -777,8 +777,11 @@ use with transparent proxy servers.
.Pp
To enable
.Cm fwd
a custom kernel needs to be compiled with the option
.Cd "options IPFIREWALL_FORWARD" .
the
.Xr sysctl 8
variable
.Va net.pfil.forward
should be set to 1.
.It Cm nat Ar nat_nr | tablearg
Pass packet to a
nat instance

View File

@ -1,7 +1,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd September 1, 2006
.Dd October 25, 2012
.Dt IPFW 4
.Os
.Sh NAME
@ -20,7 +20,6 @@ Other related kernel options
which may also be useful are:
.Bd -ragged -offset indent
.Cd "options IPFIREWALL_DEFAULT_TO_ACCEPT"
.Cd "options IPFIREWALL_FORWARD"
.Cd "options IPFIREWALL_VERBOSE"
.Cd "options IPFIREWALL_VERBOSE_LIMIT=100"
.Ed
@ -71,12 +70,6 @@ from flooding system logs or causing local Denial of Service.
This option may be set to the number of packets which will be logged on
a per-entry basis before the entry is rate-limited.
.Pp
Policy routing and transparent forwarding features of
.Nm
can be enabled by
.Dv IPFIREWALL_FORWARD
kernel option.
.Pp
The user interface for
.Nm
is implemented by the

View File

@ -897,12 +897,6 @@ device lagg
# IPDIVERT enables the divert IP sockets, used by ``ipfw divert''. It
# depends on IPFIREWALL if compiled into the kernel.
#
# IPFIREWALL_FORWARD enables changing of the packet destination either
# to do some sort of policy routing or transparent proxying. Used by
# ``ipfw forward''. All redirections apply to locally generated
# packets too. Because of this great care is required when
# crafting the ruleset.
#
# IPFIREWALL_NAT adds support for in kernel nat in ipfw, and it requires
# LIBALIAS.
#
@ -923,7 +917,6 @@ options IPFIREWALL #firewall
options IPFIREWALL_VERBOSE #enable logging to syslogd(8)
options IPFIREWALL_VERBOSE_LIMIT=100 #limit verbosity
options IPFIREWALL_DEFAULT_TO_ACCEPT #allow everything by default
options IPFIREWALL_FORWARD #packet destination changes
options IPFIREWALL_NAT #ipfw kernel nat support
options IPDIVERT #divert sockets
options IPFILTER #ipfilter support

View File

@ -398,7 +398,6 @@ IPFILTER_LOG opt_ipfilter.h
IPFILTER_LOOKUP opt_ipfilter.h
IPFIREWALL opt_ipfw.h
IPFIREWALL_DEFAULT_TO_ACCEPT opt_ipfw.h
IPFIREWALL_FORWARD opt_ipfw.h
IPFIREWALL_NAT opt_ipfw.h
IPFIREWALL_VERBOSE opt_ipfw.h
IPFIREWALL_VERBOSE_LIMIT opt_ipfw.h

View File

@ -37,6 +37,7 @@
#include <sys/rmlock.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/condvar.h>
#include <sys/lock.h>
@ -64,6 +65,11 @@ VNET_DEFINE(struct pfilheadhead, pfil_head_list);
VNET_DEFINE(struct rmlock, pfil_lock);
#define V_pfil_lock VNET(pfil_lock)
VNET_DEFINE(int, pfilforward) = 0;
SYSCTL_NODE(_net, OID_AUTO, pfil, CTLFLAG_RW, 0, "Packer filter interface");
SYSCTL_VNET_INT(_net_pfil, OID_AUTO, forward, CTLFLAG_RW,
&VNET_NAME(pfilforward), 0,
"Enable forwarding performed by packet filters");
/*
* pfil_run_hooks() runs the specified packet filter hooks.
*/

View File

@ -38,11 +38,14 @@
#include <sys/_mutex.h>
#include <sys/lock.h>
#include <sys/rmlock.h>
#include <net/vnet.h>
struct mbuf;
struct ifnet;
struct inpcb;
VNET_DECLARE(int, pfilforward);
#define V_pfilforward VNET(pfilforward)
/*
* The packet filter hooks are designed for anything to call them to
* possibly intercept the packet.

View File

@ -167,9 +167,7 @@ ip_fastforward(struct mbuf *m)
uint16_t sum, ip_len, ip_off;
int error = 0;
int hlen, mtu;
#ifdef IPFIREWALL_FORWARD
struct m_tag *fwd_tag;
#endif
struct m_tag *fwd_tag = NULL;
/*
* Are we active and forwarding packets?
@ -372,14 +370,13 @@ ip_fastforward(struct mbuf *m)
* Go on with new destination address
*/
}
#ifdef IPFIREWALL_FORWARD
if (m->m_flags & M_FASTFWD_OURS) {
/*
* ipfw changed it for a local address on this host.
*/
goto forwardlocal;
}
#endif /* IPFIREWALL_FORWARD */
passin:
/*
@ -449,20 +446,13 @@ ip_fastforward(struct mbuf *m)
/*
* Destination address changed?
*/
#ifndef IPFIREWALL_FORWARD
if (odest.s_addr != dest.s_addr) {
#else
fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
if (V_pfilforward != 0)
fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
if (odest.s_addr != dest.s_addr || fwd_tag != NULL) {
#endif /* IPFIREWALL_FORWARD */
/*
* Is it now for a local address on this host?
*/
#ifndef IPFIREWALL_FORWARD
if (in_localip(dest)) {
#else
if (m->m_flags & M_FASTFWD_OURS || in_localip(dest)) {
#endif /* IPFIREWALL_FORWARD */
forwardlocal:
/*
* Return packet for processing by ip_input().
@ -475,13 +465,11 @@ ip_fastforward(struct mbuf *m)
/*
* Redo route lookup with new destination address
*/
#ifdef IPFIREWALL_FORWARD
if (fwd_tag) {
dest.s_addr = ((struct sockaddr_in *)
(fwd_tag + 1))->sin_addr.s_addr;
m_tag_delete(m, fwd_tag);
}
#endif /* IPFIREWALL_FORWARD */
RTFREE(ro.ro_rt);
if ((dst = ip_findroute(&ro, dest, m)) == NULL)
return NULL; /* icmp unreach already sent */

View File

@ -509,7 +509,9 @@ ip_input(struct mbuf *m)
dchg = (odst.s_addr != ip->ip_dst.s_addr);
ifp = m->m_pkthdr.rcvif;
#ifdef IPFIREWALL_FORWARD
if (V_pfilforward == 0)
goto passin;
if (m->m_flags & M_FASTFWD_OURS) {
m->m_flags &= ~M_FASTFWD_OURS;
goto ours;
@ -523,7 +525,6 @@ ip_input(struct mbuf *m)
ip_forward(m, dchg);
return;
}
#endif /* IPFIREWALL_FORWARD */
passin:

View File

@ -129,9 +129,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
struct route iproute;
struct rtentry *rte; /* cache for ro->ro_rt */
struct in_addr odst;
#ifdef IPFIREWALL_FORWARD
struct m_tag *fwd_tag = NULL;
#endif
#ifdef IPSEC
int no_route_but_check_spd = 0;
#endif
@ -218,11 +216,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
ro->ro_lle = NULL;
rte = NULL;
}
#ifdef IPFIREWALL_FORWARD
if (rte == NULL && fwd_tag == NULL) {
#else
if (rte == NULL) {
#endif
bzero(dst, sizeof(*dst));
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
@ -543,7 +537,9 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
}
}
#ifdef IPFIREWALL_FORWARD
if (V_pfilforward == 0)
goto passout;
/* See if local, if yes, send it to netisr with IP_FASTFWD_OURS. */
if (m->m_flags & M_FASTFWD_OURS) {
if (m->m_pkthdr.rcvif == NULL)
@ -574,7 +570,6 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
ifa_free(&ia->ia_ifa);
goto again;
}
#endif /* IPFIREWALL_FORWARD */
passout:
/* 127/8 must not appear on wire - RFC1122. */

View File

@ -75,6 +75,7 @@ __FBSDID("$FreeBSD$");
#include <vm/uma.h>
#include <net/if.h>
#include <net/pfil.h>
#include <net/route.h>
#include <net/vnet.h>
@ -544,9 +545,7 @@ tcp_input(struct mbuf *m, int off0)
uint8_t sig_checked = 0;
#endif
uint8_t iptos = 0;
#ifdef IPFIREWALL_FORWARD
struct m_tag *fwd_tag;
#endif
struct m_tag *fwd_tag = NULL;
#ifdef INET6
struct ip6_hdr *ip6 = NULL;
int isipv6;
@ -754,15 +753,13 @@ tcp_input(struct mbuf *m, int off0)
}
#endif
#ifdef IPFIREWALL_FORWARD
/*
* Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.
*/
fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
#endif /* IPFIREWALL_FORWARD */
if (V_pfilforward != 0)
fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
#ifdef INET6
#ifdef IPFIREWALL_FORWARD
if (isipv6 && fwd_tag != NULL) {
struct sockaddr_in6 *next_hop6;
@ -788,9 +785,7 @@ tcp_input(struct mbuf *m, int off0)
}
/* Remove the tag from the packet. We don't need it anymore. */
m_tag_delete(m, fwd_tag);
} else
#endif /* IPFIREWALL_FORWARD */
if (isipv6) {
} else if (isipv6) {
inp = in6_pcblookup_mbuf(&V_tcbinfo, &ip6->ip6_src,
th->th_sport, &ip6->ip6_dst, th->th_dport,
INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB,
@ -801,7 +796,6 @@ tcp_input(struct mbuf *m, int off0)
else
#endif
#ifdef INET
#ifdef IPFIREWALL_FORWARD
if (fwd_tag != NULL) {
struct sockaddr_in *next_hop;
@ -828,7 +822,6 @@ tcp_input(struct mbuf *m, int off0)
/* Remove the tag from the packet. We don't need it anymore. */
m_tag_delete(m, fwd_tag);
} else
#endif /* IPFIREWALL_FORWARD */
inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src,
th->th_sport, ip->ip_dst, th->th_dport,
INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB,

View File

@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include <vm/uma.h>
#include <net/if.h>
#include <net/pfil.h>
#include <net/route.h>
#include <netinet/in.h>
@ -341,9 +342,7 @@ udp_input(struct mbuf *m, int off)
uint16_t len, ip_len;
struct ip save_ip;
struct sockaddr_in udp_in;
#ifdef IPFIREWALL_FORWARD
struct m_tag *fwd_tag;
#endif
ifp = m->m_pkthdr.rcvif;
UDPSTAT_INC(udps_ipackets);
@ -546,12 +545,12 @@ udp_input(struct mbuf *m, int off)
/*
* Locate pcb for datagram.
*/
#ifdef IPFIREWALL_FORWARD
/*
* Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.
*/
fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
if (fwd_tag != NULL) {
if (V_pfilforward != 0 &&
(fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL) {
struct sockaddr_in *next_hop;
next_hop = (struct sockaddr_in *)(fwd_tag + 1);
@ -577,7 +576,6 @@ udp_input(struct mbuf *m, int off)
/* Remove the tag from the packet. We don't need it anymore. */
m_tag_delete(m, fwd_tag);
} else
#endif /* IPFIREWALL_FORWARD */
inp = in_pcblookup_mbuf(&V_udbinfo, ip->ip_src, uh->uh_sport,
ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD |
INPLOOKUP_RLOCKPCB, ifp, m);

View File

@ -108,9 +108,7 @@ ip6_forward(struct mbuf *m, int srcrt)
#ifdef SCTP
int sw_csum;
#endif
#ifdef IPFIREWALL_FORWARD
struct m_tag *fwd_tag;
#endif
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
#ifdef IPSEC
@ -359,9 +357,7 @@ ip6_forward(struct mbuf *m, int srcrt)
dst->sin6_len = sizeof(struct sockaddr_in6);
dst->sin6_family = AF_INET6;
dst->sin6_addr = ip6->ip6_dst;
#ifdef IPFIREWALL_FORWARD
again2:
#endif
rin6.ro_rt = in6_rtalloc1((struct sockaddr *)dst, 0, 0, M_GETFIB(m));
if (rin6.ro_rt != NULL)
RT_UNLOCK(rin6.ro_rt);
@ -596,7 +592,8 @@ ip6_forward(struct mbuf *m, int srcrt)
goto again; /* Redo the routing table lookup. */
}
#ifdef IPFIREWALL_FORWARD
if (V_pfilforward == 0)
goto pass;
/* See if local, if yes, send it to netisr. */
if (m->m_flags & M_FASTFWD_OURS) {
if (m->m_pkthdr.rcvif == NULL)
@ -622,7 +619,6 @@ ip6_forward(struct mbuf *m, int srcrt)
m_tag_delete(m, fwd_tag);
goto again2;
}
#endif /* IPFIREWALL_FORWARD */
pass:
error = nd6_output(rt->rt_ifp, origifp, m, dst, rt);

View File

@ -628,7 +628,8 @@ ip6_input(struct mbuf *m)
ip6 = mtod(m, struct ip6_hdr *);
srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst);
#ifdef IPFIREWALL_FORWARD
if (V_pfilforward == 0)
goto passin;
if (m->m_flags & M_FASTFWD_OURS) {
m->m_flags &= ~M_FASTFWD_OURS;
ours = 1;
@ -644,7 +645,6 @@ ip6_input(struct mbuf *m)
ip6_forward(m, 1);
goto out;
}
#endif /* IPFIREWALL_FORWARD */
passin:
/*

View File

@ -257,9 +257,7 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
int segleft_org = 0;
struct secpolicy *sp = NULL;
#endif /* IPSEC */
#ifdef IPFIREWALL_FORWARD
struct m_tag *fwd_tag;
#endif
ip6 = mtod(m, struct ip6_hdr *);
if (ip6 == NULL) {
@ -915,7 +913,8 @@ skip_ipsec2:;
goto again; /* Redo the routing table lookup. */
}
#ifdef IPFIREWALL_FORWARD
if (V_pfilforward == 0)
goto passout;
/* See if local, if yes, send it to netisr. */
if (m->m_flags & M_FASTFWD_OURS) {
if (m->m_pkthdr.rcvif == NULL)
@ -941,7 +940,6 @@ skip_ipsec2:;
m_tag_delete(m, fwd_tag);
goto again;
}
#endif /* IPFIREWALL_FORWARD */
passout:
/*

View File

@ -92,6 +92,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_types.h>
#include <net/pfil.h>
#include <net/route.h>
#include <netinet/in.h>
@ -182,9 +183,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
int off = *offp;
int plen, ulen;
struct sockaddr_in6 fromsa;
#ifdef IPFIREWALL_FORWARD
struct m_tag *fwd_tag;
#endif
uint16_t uh_sum;
ifp = m->m_pkthdr.rcvif;
@ -393,12 +392,12 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
/*
* Locate pcb for datagram.
*/
#ifdef IPFIREWALL_FORWARD
/*
* Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.
*/
fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
if (fwd_tag != NULL) {
if (V_pfilforward != 0 &&
(fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL) {
struct sockaddr_in6 *next_hop6;
next_hop6 = (struct sockaddr_in6 *)(fwd_tag + 1);
@ -425,7 +424,6 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
/* Remove the tag from the packet. We don't need it anymore. */
m_tag_delete(m, fwd_tag);
} else
#endif /* IPFIREWALL_FORWARD */
inp = in6_pcblookup_mbuf(&V_udbinfo, &ip6->ip6_src,
uh->uh_sport, &ip6->ip6_dst, uh->uh_dport,
INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB,

View File

@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/route.h>
#include <net/pf_mtag.h>
#include <net/pfil.h>
#include <net/vnet.h>
#include <netinet/in.h>
@ -2534,12 +2535,7 @@ ipfw_init(void)
"(+ipv6) "
#endif
"initialized, divert %s, nat %s, "
"rule-based forwarding "
#ifdef IPFIREWALL_FORWARD
"enabled, "
#else
"disabled, "
#endif
"rule-based forwarding turned %s, "
"default to %s, logging ",
#ifdef IPDIVERT
"enabled",
@ -2551,6 +2547,7 @@ ipfw_init(void)
#else
"loadable",
#endif
V_pfilforward ? "on": "off",
default_to_accept ? "accept" : "deny");
/*

View File

@ -159,7 +159,9 @@ ipfw_check_packet(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
/* next_hop may be set by ipfw_chk */
if (args.next_hop == NULL && args.next_hop6 == NULL)
break; /* pass */
#if !defined(IPFIREWALL_FORWARD) || (!defined(INET6) && !defined(INET))
if (V_pfilforward == 0)
break;
#if (!defined(INET6) && !defined(INET))
ret = EACCES;
#else
{
@ -210,7 +212,7 @@ ipfw_check_packet(void *arg, struct mbuf **m0, struct ifnet *ifp, int dir,
#endif
m_tag_prepend(*m0, fwd_tag);
}
#endif /* IPFIREWALL_FORWARD */
#endif /* INET || INET6 */
break;
case IP_FW_DENY:

View File

@ -708,23 +708,14 @@ check_ipfw_struct(struct ip_fw *rule, int size)
goto check_action;
case O_FORWARD_IP:
#ifdef IPFIREWALL_FORWARD
if (cmdlen != F_INSN_SIZE(ipfw_insn_sa))
goto bad_size;
goto check_action;
#else
return EINVAL;
#endif
#ifdef INET6
case O_FORWARD_IP6:
#ifdef IPFIREWALL_FORWARD
if (cmdlen != F_INSN_SIZE(ipfw_insn_sa6))
goto bad_size;
goto check_action;
#else
return (EINVAL);
#endif
#endif /* INET6 */
case O_DIVERT: