Introduce a new feature in IPFW: Check of the source or destination
address is configured on a interface. This is useful for routers with dynamic interfaces. It is now possible to say: 0100 allow tcp from any to any established 0200 skipto 1000 tcp from any to any 0300 allow ip from any to any 1000 allow tcp from 1.2.3.4 to me 22 1010 deny tcp from any to me 22 1020 allow tcp from any to any and not have to worry about the behaviour if dynamic interfaces configure new IP numbers later on. The check is semi expensive (traverses the interface address list) so it should be protected as in the above example if high performance is a requirement.
This commit is contained in:
parent
6d110b1be0
commit
bb07ec8c84
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=72440
@ -478,9 +478,23 @@ or
|
||||
.Cm all
|
||||
keywords mean any protocol will match.
|
||||
.It Ar src No and Ar dst :
|
||||
.Cm any
|
||||
|
|
||||
.Cm me
|
||||
|
|
||||
.Op Cm not
|
||||
.Aq Ar address Ns / Ns Ar mask
|
||||
.Op Ar ports
|
||||
.Pp
|
||||
Specifying
|
||||
.Cm any
|
||||
makes the rule match any IP number.
|
||||
.Pp
|
||||
Specifying
|
||||
.Cm me
|
||||
makes the rule match any IP number configured on an interface in the system.
|
||||
This is an computationally semi-expensive check which should be used with care.
|
||||
.Pp
|
||||
The
|
||||
.Aq Ar address Ns / Ns Ar mask
|
||||
may be specified as:
|
||||
|
@ -276,17 +276,20 @@ show_ipfw(struct ip_fw *chain, int pcwidth, int bcwidth)
|
||||
else
|
||||
printf(" %u", chain->fw_prot);
|
||||
|
||||
printf(" from %s", chain->fw_flg & IP_FW_F_INVSRC ? "not " : "");
|
||||
if (chain->fw_flg & IP_FW_F_SME) {
|
||||
printf(" from me");
|
||||
} else {
|
||||
printf(" from %s", chain->fw_flg & IP_FW_F_INVSRC ? "not " : "");
|
||||
|
||||
adrt=ntohl(chain->fw_smsk.s_addr);
|
||||
if (adrt==ULONG_MAX && do_resolv) {
|
||||
adrt=(chain->fw_src.s_addr);
|
||||
he=gethostbyaddr((char *)&adrt,sizeof(u_long),AF_INET);
|
||||
if (he==NULL) {
|
||||
printf(inet_ntoa(chain->fw_src));
|
||||
} else
|
||||
printf("%s",he->h_name);
|
||||
} else {
|
||||
adrt=ntohl(chain->fw_smsk.s_addr);
|
||||
if (adrt==ULONG_MAX && do_resolv) {
|
||||
adrt=(chain->fw_src.s_addr);
|
||||
he=gethostbyaddr((char *)&adrt,sizeof(u_long),AF_INET);
|
||||
if (he==NULL) {
|
||||
printf(inet_ntoa(chain->fw_src));
|
||||
} else
|
||||
printf("%s",he->h_name);
|
||||
} else {
|
||||
if (adrt!=ULONG_MAX) {
|
||||
mb=mask_bits(chain->fw_smsk);
|
||||
if (mb == 0) {
|
||||
@ -303,6 +306,7 @@ show_ipfw(struct ip_fw *chain, int pcwidth, int bcwidth)
|
||||
}
|
||||
} else
|
||||
printf(inet_ntoa(chain->fw_src));
|
||||
}
|
||||
}
|
||||
|
||||
if (chain->fw_prot == IPPROTO_TCP || chain->fw_prot == IPPROTO_UDP) {
|
||||
@ -318,33 +322,37 @@ show_ipfw(struct ip_fw *chain, int pcwidth, int bcwidth)
|
||||
}
|
||||
}
|
||||
|
||||
printf(" to %s", chain->fw_flg & IP_FW_F_INVDST ? "not " : "");
|
||||
if (chain->fw_flg & IP_FW_F_DME) {
|
||||
printf(" to me");
|
||||
} else {
|
||||
printf(" to %s", chain->fw_flg & IP_FW_F_INVDST ? "not " : "");
|
||||
|
||||
adrt=ntohl(chain->fw_dmsk.s_addr);
|
||||
if (adrt==ULONG_MAX && do_resolv) {
|
||||
adrt=(chain->fw_dst.s_addr);
|
||||
he=gethostbyaddr((char *)&adrt,sizeof(u_long),AF_INET);
|
||||
if (he==NULL) {
|
||||
printf(inet_ntoa(chain->fw_dst));
|
||||
} else
|
||||
printf("%s",he->h_name);
|
||||
} else {
|
||||
if (adrt!=ULONG_MAX) {
|
||||
mb=mask_bits(chain->fw_dmsk);
|
||||
if (mb == 0) {
|
||||
printf("any");
|
||||
} else {
|
||||
if (mb > 0) {
|
||||
printf(inet_ntoa(chain->fw_dst));
|
||||
printf("/%d",mb);
|
||||
adrt=ntohl(chain->fw_dmsk.s_addr);
|
||||
if (adrt==ULONG_MAX && do_resolv) {
|
||||
adrt=(chain->fw_dst.s_addr);
|
||||
he=gethostbyaddr((char *)&adrt,sizeof(u_long),AF_INET);
|
||||
if (he==NULL) {
|
||||
printf(inet_ntoa(chain->fw_dst));
|
||||
} else
|
||||
printf("%s",he->h_name);
|
||||
} else {
|
||||
if (adrt!=ULONG_MAX) {
|
||||
mb=mask_bits(chain->fw_dmsk);
|
||||
if (mb == 0) {
|
||||
printf("any");
|
||||
} else {
|
||||
printf(inet_ntoa(chain->fw_dst));
|
||||
printf(":");
|
||||
printf(inet_ntoa(chain->fw_dmsk));
|
||||
if (mb > 0) {
|
||||
printf(inet_ntoa(chain->fw_dst));
|
||||
printf("/%d",mb);
|
||||
} else {
|
||||
printf(inet_ntoa(chain->fw_dst));
|
||||
printf(":");
|
||||
printf(inet_ntoa(chain->fw_dmsk));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
printf(inet_ntoa(chain->fw_dst));
|
||||
} else
|
||||
printf(inet_ntoa(chain->fw_dst));
|
||||
}
|
||||
}
|
||||
|
||||
if (chain->fw_prot == IPPROTO_TCP || chain->fw_prot == IPPROTO_UDP) {
|
||||
@ -857,8 +865,8 @@ show_usage(const char *fmt, ...)
|
||||
" reset|count|skipto num|divert port|tee port|fwd ip|\n"
|
||||
" pipe num} [log [logamount count]]\n"
|
||||
" proto: {ip|tcp|udp|icmp|<number>}\n"
|
||||
" src: from [not] {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n"
|
||||
" dst: to [not] {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n"
|
||||
" src: from [not] {me|any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n"
|
||||
" dst: to [not] {me|any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n"
|
||||
" extras:\n"
|
||||
" uid {user id}\n"
|
||||
" gid {group id}\n"
|
||||
@ -1792,7 +1800,12 @@ add(ac,av)
|
||||
if (!ac)
|
||||
show_usage("missing arguments");
|
||||
|
||||
fill_ip(&rule.fw_src, &rule.fw_smsk, &ac, &av);
|
||||
if (ac && !strncmp(*av,"me",strlen(*av))) {
|
||||
rule.fw_flg |= IP_FW_F_SME;
|
||||
av++; ac--;
|
||||
} else {
|
||||
fill_ip(&rule.fw_src, &rule.fw_smsk, &ac, &av);
|
||||
}
|
||||
|
||||
if (ac && (isdigit(**av) || lookup_port(*av, rule.fw_prot, 1, 1) >= 0)) {
|
||||
u_short nports = 0;
|
||||
@ -1819,7 +1832,13 @@ add(ac,av)
|
||||
if (!ac)
|
||||
show_usage("missing arguments");
|
||||
|
||||
fill_ip(&rule.fw_dst, &rule.fw_dmsk, &ac, &av);
|
||||
|
||||
if (ac && !strncmp(*av,"me",strlen(*av))) {
|
||||
rule.fw_flg |= IP_FW_F_DME;
|
||||
av++; ac--;
|
||||
} else {
|
||||
fill_ip(&rule.fw_dst, &rule.fw_dmsk, &ac, &av);
|
||||
}
|
||||
|
||||
if (ac && (isdigit(**av) || lookup_port(*av, rule.fw_prot, 1, 1) >= 0)) {
|
||||
u_short nports = 0;
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/in_pcb.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_var.h>
|
||||
@ -947,6 +948,7 @@ ip_fw_chk(struct ip **pip, int hlen,
|
||||
struct ip_fw *f = NULL, *rule = NULL;
|
||||
struct ip *ip = *pip;
|
||||
struct ifnet *const rif = (*m)->m_pkthdr.rcvif;
|
||||
struct ifnet *tif;
|
||||
u_short offset = 0 ;
|
||||
u_short src_port = 0, dst_port = 0;
|
||||
struct in_addr src_ip, dst_ip; /* XXX */
|
||||
@ -1111,6 +1113,16 @@ ip_fw_chk(struct ip **pip, int hlen,
|
||||
if ((f->fw_flg & IP_FW_F_FRAG) && offset == 0 )
|
||||
continue;
|
||||
|
||||
if (f->fw_flg & IP_FW_F_SME) {
|
||||
INADDR_TO_IFP(src_ip, tif);
|
||||
if (tif == NULL)
|
||||
continue;
|
||||
}
|
||||
if (f->fw_flg & IP_FW_F_DME) {
|
||||
INADDR_TO_IFP(dst_ip, tif);
|
||||
if (tif == NULL)
|
||||
continue;
|
||||
}
|
||||
/* If src-addr doesn't match, not this rule. */
|
||||
if (((f->fw_flg & IP_FW_F_INVSRC) != 0) ^ ((src_ip.s_addr
|
||||
& f->fw_smsk.s_addr) != f->fw_src.s_addr))
|
||||
|
@ -212,7 +212,10 @@ struct ipfw_dyn_rule {
|
||||
#define IP_FW_F_KEEP_S 0x08000000 /* keep state */
|
||||
#define IP_FW_F_CHECK_S 0x10000000 /* check state */
|
||||
|
||||
#define IP_FW_F_MASK 0x1FFFFFFF /* All possible flag bits mask */
|
||||
#define IP_FW_F_SME 0x20000000 /* source = me */
|
||||
#define IP_FW_F_DME 0x40000000 /* destination = me */
|
||||
|
||||
#define IP_FW_F_MASK 0x7FFFFFFF /* All possible flag bits mask */
|
||||
|
||||
/*
|
||||
* Flags for the 'fw_ipflg' field, for comparing values of ip and its protocols.
|
||||
|
Loading…
Reference in New Issue
Block a user