Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fragmented packets are dropped by the firewall #4

Open
akhilesh2410 opened this issue Feb 1, 2018 · 2 comments
Open

Fragmented packets are dropped by the firewall #4

akhilesh2410 opened this issue Feb 1, 2018 · 2 comments

Comments

@akhilesh2410
Copy link
Collaborator

akhilesh2410 commented Feb 1, 2018

I have seen that fragmented packets are dropped by the ipfilter firewall. First packet makes entry in state table and subsequent packets also able to find state table entry but are dropped by the firewall.
This issue seen for IN/OUT direction fragmented packets.

Further looking at the code i found that code in fil.c line : 2502 looks suspicious to me ,which mark the packet flag as BLOCK ,because for fragmented packet FI_FRAGBODY flag will be set and it will not be added into state table.

And mark the packet as bad packet by increment fr_bads.

-bash-4.3# ipf -V
ipf: IP Filter: v4.1.13 (480)
Kernel: IP Filter: v4.1.13
Running: yes
Log Flags: 0 = none set
Default: pass all, Logging: available
Active list: 0
Feature mask: 0x87
-bash-4.3#

@akhilesh2410
Copy link
Collaborator Author

Below code in ip_frag.c needs to be added to resolve this issue:
In Function frentry_t *fr_knownfrag(fin, passp): Line number 641:

  if ((pass & FR_KEEPSTATE) != 0)
    pass &= ~(FR_KEEPSTATE);
  if ((pass & FI_STATE) != 0)
    pass &= ~(FI_STATE);

Thanks,
Akhilesh Verma

@ishyiko
Copy link

ishyiko commented Jan 6, 2022

diff --git a/kernext/fil.c b/kernext/fil.c
index 0d529e6..25c0f5b 100644
--- a/kernext/fil.c
+++ b/kernext/fil.c
@@ -1363,7 +1363,10 @@ fr_info_t *fin;
 	if (off != 0) {
 		fi->fi_flx |= FI_FRAG;
 		off &= IP_OFFMASK;
-		if (off != 0) {
+		//check if we have IP_MF bit set in offset, if yes then only,
+		//go to loop and validate it with given condition
+		// else that would be the last fragment and should not be validated
+		if ((off & ~IP_OFFMASK) != 0) {
 			fin->fin_flx |= FI_FRAGBODY;
 			off <<= 3;
 			if ((off + fin->fin_dlen > 65535) || 
diff --git a/kernext/ip_frag.c b/kernext/ip_frag.c
index a6168ff..d5e9c18 100644
--- a/kernext/ip_frag.c
+++ b/kernext/ip_frag.c
@@ -639,6 +639,10 @@ u_32_t *passp;
 			pass = fr->fr_flags;
 			if ((pass & FR_LOGFIRST) != 0)
 				pass &= ~(FR_LOGFIRST|FR_LOG);
+			if ((pass & FR_KEEPSTATE) != 0)
+				pass &= ~(FR_KEEPSTATE);
+			if ((pass & FI_STATE) != 0)
+				pass &= ~(FI_STATE);
 			*passp = pass;
 		}
 	} 	

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants