bin/74450: enable libalias/natd to create skipto rules when punching ipfw

Joost Bekkers joost at jodocus.org
Sat Nov 27 07:50:23 PST 2004


>Number:         74450
>Category:       bin
>Synopsis:       enable libalias/natd to create skipto rules when punching ipfw
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          update
>Submitter-Id:   current-users
>Arrival-Date:   Sat Nov 27 15:50:22 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Joost Bekkers
>Release:        FreeBSD 5.3-RELEASE i386
>Organization:
>Environment:
System: FreeBSD bps.jodocus.org 5.3-RELEASE FreeBSD 5.3-RELEASE #3: Wed Nov 3 21:17:32 CET 2004 joost at bps.jodocus.org:/usr/src/sys/i386/compile/bps i386

>Description:

When using ipfw in a stateful firewall with natd it's desirable to have
natd create skipto rules instead of allow rules.

See http://lists.freebsd.org/mailman/htdig/freebsd-ipfw/2004-June/001182.html
for a description of the type of firewall I'm referring to.

>How-To-Repeat:
>Fix:

NB: The patch below also updates the man pages.

diff -c src/lib/libalias/dist/alias.h src/lib/libalias/alias.h
*** src/lib/libalias/dist/alias.h	Tue Nov 23 21:52:03 2004
--- src/lib/libalias/alias.h	Fri Nov 26 19:46:27 2004
***************
*** 126,131 ****
--- 126,132 ----
  struct libalias *LibAliasInit(struct libalias *);
  void		LibAliasSetAddress(struct libalias *, struct in_addr _addr);
  void		LibAliasSetFWBase(struct libalias *, unsigned int _base, unsigned int _num);
+ void		LibAliasSetFWSkipToRule(struct libalias *, unsigned int _rulenr);
  void		LibAliasSetSkinnyPort(struct libalias *, unsigned int _port);
  unsigned int
  		LibAliasSetMode(struct libalias *, unsigned int _flags, unsigned int _mask);
diff -c src/lib/libalias/dist/alias_db.c src/lib/libalias/alias_db.c
*** src/lib/libalias/dist/alias_db.c	Tue Nov 23 21:52:03 2004
--- src/lib/libalias/alias_db.c	Fri Nov 26 19:46:27 2004
***************
*** 2531,2537 ****
  
  static int
  fill_rule(void *buf, int bufsize, int rulenum,
!     enum ipfw_opcodes action, int proto,
      struct in_addr sa, u_int16_t sp, struct in_addr da, u_int16_t dp)
  {
  	struct ip_fw *rule = (struct ip_fw *)buf;
--- 2531,2537 ----
  
  static int
  fill_rule(void *buf, int bufsize, int rulenum,
!     enum ipfw_opcodes action, int arg1, int proto,
      struct in_addr sa, u_int16_t sp, struct in_addr da, u_int16_t dp)
  {
  	struct ip_fw *rule = (struct ip_fw *)buf;
***************
*** 2547,2553 ****
  	cmd = fill_one_port(cmd, O_IP_DSTPORT, dp);
  
  	rule->act_ofs = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
! 	cmd = fill_cmd(cmd, action, F_INSN_SIZE(ipfw_insn), 0, 0);
  
  	rule->cmd_len = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
  
--- 2547,2553 ----
  	cmd = fill_one_port(cmd, O_IP_DSTPORT, dp);
  
  	rule->act_ofs = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
! 	cmd = fill_cmd(cmd, action, F_INSN_SIZE(ipfw_insn), 0, arg1);
  
  	rule->cmd_len = (u_int32_t *) cmd - (u_int32_t *) rule->cmd;
  
***************
*** 2652,2660 ****
  	if (GetOriginalPort(lnk) != 0 && GetDestPort(lnk) != 0) {
  		u_int32_t rulebuf[255];
  		int i;
  
  		i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
! 		    O_ACCEPT, IPPROTO_TCP,
  		    GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)),
  		    GetDestAddress(lnk), ntohs(GetDestPort(lnk)));
  		r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
--- 2652,2666 ----
  	if (GetOriginalPort(lnk) != 0 && GetDestPort(lnk) != 0) {
  		u_int32_t rulebuf[255];
  		int i;
+ 		enum ipfw_opcodes action;
+ 
+ 		if (la->fireWallSkipTo==0)
+ 		    action=O_ACCEPT;
+ 		else
+ 		    action=O_SKIPTO;
  
  		i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
! 		    action, la->fireWallSkipTo, IPPROTO_TCP,
  		    GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)),
  		    GetDestAddress(lnk), ntohs(GetDestPort(lnk)));
  		r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
***************
*** 2662,2668 ****
  			err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
  
  		i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
! 		    O_ACCEPT, IPPROTO_TCP,
  		    GetDestAddress(lnk), ntohs(GetDestPort(lnk)),
  		    GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)));
  		r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
--- 2668,2674 ----
  			err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)");
  
  		i = fill_rule(rulebuf, sizeof(rulebuf), fwhole,
! 		    action, la->fireWallSkipTo, IPPROTO_TCP,
  		    GetDestAddress(lnk), ntohs(GetDestPort(lnk)),
  		    GetOriginalAddress(lnk), ntohs(GetOriginalPort(lnk)));
  		r = setsockopt(la->fireWallFD, IPPROTO_IP, IP_FW_ADD, rulebuf, i);
***************
*** 2675,2681 ****
  	rule.fw_number = fwhole;
  	IP_FW_SETNSRCP(&rule, 1);	/* Number of source ports. */
  	IP_FW_SETNDSTP(&rule, 1);	/* Number of destination ports. */
! 	rule.fw_flg = IP_FW_F_ACCEPT | IP_FW_F_IN | IP_FW_F_OUT;
  	rule.fw_prot = IPPROTO_TCP;
  	rule.fw_smsk.s_addr = INADDR_BROADCAST;
  	rule.fw_dmsk.s_addr = INADDR_BROADCAST;
--- 2681,2689 ----
  	rule.fw_number = fwhole;
  	IP_FW_SETNSRCP(&rule, 1);	/* Number of source ports. */
  	IP_FW_SETNDSTP(&rule, 1);	/* Number of destination ports. */
! 	rule.fw_flg = (la->fireWallSkipTo==0)?IP_FW_F_ACCEPT:IP_FW_F_SKIPTO;
! 	rule.fw_flg |= IP_FW_F_IN | IP_FW_F_OUT;
! 	rule.fw_skipto_rule = la->fireWallSkipTo;
  	rule.fw_prot = IPPROTO_TCP;
  	rule.fw_smsk.s_addr = INADDR_BROADCAST;
  	rule.fw_dmsk.s_addr = INADDR_BROADCAST;
***************
*** 2778,2783 ****
--- 2786,2799 ----
  #ifndef NO_FW_PUNCH
  	la->fireWallBaseNum = base;
  	la->fireWallNumNums = num;
+ #endif
+ }
+ 
+ void
+ LibAliasSetFWSkipToRule(struct libalias *la, unsigned int rulenr)
+ {
+ #ifndef NO_FW_PUNCH
+ 	la->fireWallSkipTo = rulenr;
  #endif
  }
  
diff -c src/lib/libalias/dist/alias_local.h src/lib/libalias/alias_local.h
*** src/lib/libalias/dist/alias_local.h	Tue Nov 23 21:52:03 2004
--- src/lib/libalias/alias_local.h	Fri Nov 26 19:46:27 2004
***************
*** 121,126 ****
--- 121,128 ----
  						 * free for our use */
  	int		fireWallNumNums;	/* How many entries can we
  						 * use? */
+ 	int		fireWallSkipTo;		/* 0 == accept
+ 						 * else rule number to skip to */
  	int		fireWallActiveNum;	/* Which entry did we last
  						 * use? */
  	char           *fireWallField;	/* bool array for entries */
diff -c src/lib/libalias/dist/libalias.3 src/lib/libalias/libalias.3
*** src/lib/libalias/dist/libalias.3	Tue Nov 23 21:52:03 2004
--- src/lib/libalias/libalias.3	Fri Nov 26 19:46:27 2004
***************
*** 270,275 ****
--- 270,286 ----
  .Ed
  .Pp
  .Ft void
+ .Fn LibAliasSetFWSkipToRule "struct libalias *" "unsigned int rulenr"
+ .Bd -ragged -offset indent
+ Cause
+ .Nm
+ to create skipto rules instead of the default allow rules
+ when making holes in the firewall. Setting
+ .Fa rulenr
+ to 0 will restore the default behavior of creating allow rules.
+ .Ed
+ .Pp
+ .Ft void
  .Fn LibAliasSkinnyPort "struct libalias *" "unsigned int port"
  .Bd -ragged -offset indent
  Set the TCP port used by the Skinny Station protocol.
diff -c src/sbin/natd/dist/natd.8 src/sbin/natd/natd.8
*** src/sbin/natd/dist/natd.8	Fri Nov 26 19:10:27 2004
--- src/sbin/natd/natd.8	Sat Nov 27 16:34:16 2004
***************
*** 31,36 ****
--- 31,37 ----
  .Op Fl log_denied
  .Op Fl log_facility Ar facility_name
  .Op Fl punch_fw Ar firewall_range
+ .Op Fl punch_skipto Ar rule_number
  .Op Fl skinny_port Ar port
  .Op Fl log_ipfw_denied
  .Op Fl pid_file | P Ar pidfile
***************
*** 484,489 ****
--- 485,493 ----
  .Ar basenumber
  will be used for punching firewall holes.
  The range will be cleared for all rules on startup.
+ .It Fl punch_skipto Ar rule_number
+ Instead of the default allow rules, create skipto rules which skip to
+ .Ar rule_number .
  .It Fl skinny_port Ar port
  This option allows you to specify the TCP port used for
  the Skinny Station protocol.
diff -c src/sbin/natd/dist/natd.c src/sbin/natd/natd.c
*** src/sbin/natd/dist/natd.c	Fri Nov 26 19:09:06 2004
--- src/sbin/natd/natd.c	Fri Nov 26 19:35:50 2004
***************
*** 127,132 ****
--- 127,133 ----
  static int      StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, port_range *portRange);
  static void	ParseArgs (int argc, char** argv);
  static void	SetupPunchFW(const char *strValue);
+ static void	SetupPunchSkipTo(const char *strValue);
  static void	SetupSkinnyPort(const char *strValue);
  static void	NewInstance(const char *name);
  static void	DoGlobal (int fd);
***************
*** 1017,1022 ****
--- 1018,1024 ----
   	LogDenied,
   	LogFacility,
  	PunchFW,
+ 	PunchSkipTo,
  	SkinnyPort,
  	LogIpfwDenied,
  	PidFile
***************
*** 1247,1252 ****
--- 1249,1262 ----
  		"punch_fw",
  		NULL },
  
+ 	{ PunchSkipTo,
+ 		0,
+ 		String,
+ 	        "rulenumber",
+ 		"use skipto instead of permit action when punching the firewall",
+ 		"punch_skipto",
+ 		NULL },
+ 
  	{ SkinnyPort,
  		0,
  		String,
***************
*** 1465,1470 ****
--- 1475,1484 ----
  		SetupPunchFW(strValue);
  		break;
  
+ 	case PunchSkipTo:
+ 		SetupPunchSkipTo(strValue);
+ 		break;
+ 
  	case SkinnyPort:
  		SetupSkinnyPort(strValue);
  		break;
***************
*** 1918,1923 ****
--- 1932,1948 ----
  
  	LibAliasSetFWBase(mla, base, num);
  	(void)LibAliasSetMode(mla, PKT_ALIAS_PUNCH_FW, PKT_ALIAS_PUNCH_FW);
+ }
+ 
+ static void
+ SetupPunchSkipTo(const char *strValue)
+ {
+ 	unsigned int rule;
+ 
+ 	if (sscanf(strValue, "%u", &rule) != 1)
+ 		errx(1, "punch_skipto: rule number required");
+ 
+ 	LibAliasSetFWSkipToRule(mla, rule);
  }
  
  static void
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list