After Upgrading FreeBSD from 13.2 to 14.1: Apache has problems delivering large files

Hi,
I need some help because I can't figure out the issue I'm currently facing.
My environment worked without any issue with FreeBSD 13.2, but after upgrading to 14.1 I have problems with Apache:
Apache seems to have issues now with delivering larger files. E.g. I'm running a phpbb3 bulletin board and the normal board is loaded but when I open a posting that includes a larger image, this image is only partly loaded.
And my Nextcloud doesn't even showed the login form because it is implemented by a larger js-library that is not fully loaded in my browser from my Apache.
Unfortunately I haven't found any useful error / log message yet, that points me to the problem.
I've enabled debug logging for Apache and php-fpm, but only the typicall info / debug message, no warning or error logged.

My Apache webserver runs in a iocage managed jail and I have a pound proxy in front. But I removed the proxy for testing purposes and that didn't helped, so I assume pound is not causing the problem.
Maybe something has changed in the networking between the host system and my jail between FreeBSD 13.2 and 14.1? A smaller MTU or whatever? I have no clue.

I know, I have less information to provide for really helping me, but maybe someone has at least an idea what could be the reason / has had a similar problem in that past.
Or has a good hint how to debug that issue...
Any help is welcome!

Thank you!

Kind regards,
Fool

PS: Hope this is the right section in this board for my problem, otherwise please let me know and I'll move it to the right section.
 
Hello,

when I use fetch from another FreeBSD machine I get the following output:

Code:
%fetch --verbose https://<myserver>/foo.jpg
resolving server address: <myserver>:443
SSL options: 82004850
Peer verification enabled
Using OpenSSL default CA cert file and path
Verify hostname
TLSv1.3 connection established using TLS_AES_256_GCM_SHA384
Certificate subject: /CN=<myserver>
Certificate issuer: /C=US/O=Let's Encrypt/CN=R3
requesting https://<myserver>/foo.jpg
server requires authorization
resolving server address: <myserver>:443
SSL options: 82004850
Peer verification enabled
Using OpenSSL default CA cert file and path
Verify hostname
TLSv1.3 connection established using TLS_AES_256_GCM_SHA384
Certificate subject: /CN=<myserver>
Certificate issuer: /C=US/O=Let's Encrypt/CN=R3
requesting https://<myserver>/foo.jpg
Authentication required for <https://<myserver>:443/>!
Login: <myuser>
Password:
remote size / mtime: 3700905 / 1718201000
foo.jpg                                        13% of 3614 kB  239 kBps    12s
fetch: foo.jpg appears to be truncated: 495616/3700905 bytes

If I use Firefox and enable the web developers tool I see a "NS_ERROR_NET_PARTIAL_TRANSFER" for the HTTP GET request.

I'm currently struggling with doing the request from my server itself. I'm somehow blocked by my own IPFW firewall rules. :rolleyes:
I'll try later again if I get this to work. Does the fetch(1) error message does give you a hint?

Thanks!

Kind regards,
Fool
 
Hi,
I've continued my testing:
I've disabled HTTPS / TLS and use plain HTTP instead, to verify that it's not an issue with TLS.
That results in a really interesting behaviour:
  1. Loading my foo.jpg in the browser (Firefox) always fails with the image only partly loaded. The Network debugger of the web developer tools say "NS_ERROR_NET_PARTIAL_TRANSFER".
  2. Using fetch(1) from another FreeBSD machine works in most cases, only very seldom I get a message like "fetch: foo.jpg appears to be truncated: 495616/3700905 bytes".
  3. Using fetch(1) from my server itself (technically from one jail to another jail) it always works; at least I haven't seen the truncated message now during several attempts.
  4. Using wget or curl from a Linux machin always fails. wget reports something like "Just got 74348 of 3700905 bytes", curl instead with "curl: (18) transfer closed with 3268453 bytes remaining to read".
I've noticed one thing in the httpd-error.log of my Apache. Not really sure if this is really the issue, but at least it looks promising:
Code:
[http:debug] [pid 62218:tid 25952927303680] byterange_filter.c(294): [client <myip>] AH01583: Range: 1630500- | 1630500-3700904 (0 : 0 : 3700905)
If I search for that online, I do not really find good information.

Any idea? :-/

Thanks and kind regards,
Fool
 
amd64?

Apache from packages or built from ports? Assuming 2.4.59?

If built from ports, any non-default options taken? If building from ports, using base OpenSSL or the ports version (/etc/make.conf)?

I've got a test machine that I've just installed 14.1 amd64 the other day, building Apache 2.4.59 (with ports OpenSSL just because it is a habit) on there now.

Anything like this being used? https://forums.freebsd.org/threads/apache-2-4-and-accept-filters.59385/
 
I wanted to check basic FreeBSD 14.1/Apache worked and it does so far as I can see.

Test server:
Code:
# uname -a
FreeBSD sm510.user.co.nz 14.1-RELEASE FreeBSD 14.1-RELEASE releng/14.1-n267679-10e31f0946d8 GENERIC amd64
# freebsd-version -ruk
14.1-RELEASE
14.1-RELEASE
14.1-RELEASE
# pkg info | grep apache
apache24-2.4.59                Version 2.4.x of Apache web server

FreeBSD client:
Code:
user@vp2410:~ % fetch http://192.168.1.233/freebsd-src-main.zip
freebsd-src-main.zip                                   379 MB  112 MBps    03s
user@vp2410:~ % fetch http://192.168.1.233/freebsd-src-main.zip
freebsd-src-main.zip                                   379 MB  112 MBps    03s
user@vp2410:~ % fetch http://192.168.1.233/freebsd-src-main.zip
freebsd-src-main.zip                                   379 MB  112 MBps    03s
user@vp2410:~ % fetch http://192.168.1.233/freebsd-src-main.zip
freebsd-src-main.zip                                   379 MB  112 MBps    03s
user@vp2410:~ % fetch http://192.168.1.233/freebsd-src-main.zip
freebsd-src-main.zip                                   379 MB   76 MBps    05s

OpenBSD client:
Code:
devssd$ ftp http://192.168.1.233/freebsd-src-main.zip
Trying 192.168.1.233...
Requesting http://192.168.1.233/freebsd-src-main.zip
100% |********************************************************************************************************************************************************************************************************************************|   379 MB    00:03    
398427508 bytes received in 3.58 seconds (106.07 MB/s)
devssd$ ftp http://192.168.1.233/freebsd-src-main.zip 
Trying 192.168.1.233...
Requesting http://192.168.1.233/freebsd-src-main.zip
100% |********************************************************************************************************************************************************************************************************************************|   379 MB    00:04    
398427508 bytes received in 4.98 seconds (76.15 MB/s)
 
I've noticed one thing in the httpd-error.log of my Apache. Not really sure if this is really the issue, but at least it looks promising:
Code:
[http:debug] [pid 62218:tid 25952927303680] byterange_filter.c(294): [client <myip>] AH01583: Range: 1630500- | 1630500-3700904 (0 : 0 : 3700905)
If I search for that online, I do not really find good information.

modules/http/byterange_filter.c
Code:
 77 /*     
 78  * Returns: number of ranges (merged) or -1 for no-good
 79  */
 80 static int ap_set_byterange(request_rec *r, apr_off_t clength,
 81                             apr_array_header_t **indexes,
 82                             int *overlaps, int *reversals)
 83 {  

292     r->status = HTTP_PARTIAL_CONTENT;
293     r->range = apr_array_pstrcat(r->pool, merged, ',');
294     ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01583)
295                   "Range: %s | %s (%d : %d : %"APR_OFF_T_FMT")",
296                   it, r->range, *overlaps, *reversals, clength);

It is sending partial content, I think - (0 : 0 : 3700905) - 0 overlaps, 0 reversals, and the content length of 3700905. It is sending bytes from 1630500 onwards - so perhaps the client (or Apache) knows it is a partial download and requests the missing bit?

But this might be more a symptom of the issue - you know already that something is chopping up the transfers.[/CODE]
 
Have you tried other network copying e.g. scp? Just to eliminate some network issues.

Any apache modules in use? My test was with the default options selected:
Code:
% apachectl -M
AH00557: httpd: apr_sockaddr_info_get() failed for sm510.user.co.nz
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1. Set the 'ServerName' directive globally to suppress this message
Loaded Modules:
 core_module (static)
 so_module (static)
 http_module (static)
 mpm_prefork_module (shared)
 authn_file_module (shared)
 authn_core_module (shared)
 authz_host_module (shared)
 authz_groupfile_module (shared)
 authz_user_module (shared)
 authz_core_module (shared)
 access_compat_module (shared)
 auth_basic_module (shared)
 reqtimeout_module (shared)
 filter_module (shared)
 mime_module (shared)
 log_config_module (shared)
 env_module (shared)
 headers_module (shared)
 setenvif_module (shared)
 version_module (shared)
 unixd_module (shared)
 status_module (shared)
 autoindex_module (shared)
 dir_module (shared)
 alias_module (shared)
 
Hello,

I build Apache from the ports, because I need LDAP enabled for Apache which is not the case when I install it as package.
Thanks for all your proposals, I'll try / investigate this evening and then come back here.

Kind regards,
Fool
 
I'm currently struggling with doing the request from my server itself. I'm somehow blocked by my own IPFW firewall rules.

Temporarily add 'log' to all possibly relevant ipfw rules, then tail /var/log/security while fetching.

Are you using keep-state on TCP rules? If so, do you have any custom timeouts that may drop longer connections?

Check while fetching with ipfw -ted show for any expired dynamic rules.

Personally I prefer stateless rules (setup, established) for esp. inbound TCP requests. Post your ruleset or at least relevant bits if in doubt?

cheers, Ian
 
Hello,
to keep you updated:
I installed the latest Apache now directly onto my server (not inside a jail) including IPFW and it worked without any problems.
So I can exclude a general network or IPFW issue.

I currently see three potential things that could be responsible for my problem:
1) That I use Apache from ports with LDAP support compiled.
2) That my Apache is running inside a jail.
3) That I use NAT rules with IPFW that routes the incoming HTTP requests to the right jail.

As a next step I plan to use a pkg installed Apache inside the jail. If that works I guess the issue is the compiled Apache from ports.
If that also causes the problems, it must be an issue with jail and the related NAT via IPFW.

Just to be clear about that: That whole setup works successfully for several years now.
I run into the issue after upgrading from FreeBSD 13.2 to 14.1 including a recompile of the ports inside the jail.
Maybe someone has an idea what could happen during upgrading from 13.2 to 14.1 that has broken my setup?

Kind regards,
Fool
 
Hello,
I continued my testing with an Apache installed as package in a jail: Here the problem arises again.
I then installed an openssh server in the jail and did a test with scp, which also results in a not fully copied file.
So I think I can exclude Apache as the issue now and need to investigate deeper into jails and IPFW NAT.
Still wondering what could have changed here by upgrading FreeBSD, but at least I know that I do not need to dig through Apache and php logs... 😏

Kind regards,
Fool
 
So I think I can exclude Apache as the issue now and need to investigate deeper into jails and IPFW NAT.
That’s what the advice has been so far - firewall/network.

Once you’ve narrowed it down a bit more it might become clearer what caused it to happen post-upgrade.

You‘ve got a lot of moving parts so there’s a few things to eliminate - but you are making progress!
 
So I think I can exclude Apache as the issue now and need to investigate deeper into jails and IPFW NAT.

Why not show us your ipfw nat setup, in context, in case something is obvious to those of us who have used that?

In terms of Handbook Chapter (currently) 17, is this a VNET jail, or what?

cheers, Ian
 
Hello,
sure, I'll show you my ipfw rules. I'm also open for any hints etc. if there is something to improve that doesn't have to do anything with my issue. :)

It is a long time ago that I've created these jails and I'm not sure what documentation / guideline I was following. But from a quick look into the handbook I would say yes, these are VNET jails:
Each jail has an own internal IP address and is isolated from all other jails. TCP based access is strictly controlled by ipfw rules.
The idea why I'm doing this is for an additional layer of security. E.g. if someone is able to break into my Nextcloud, the attacker (at least in theory) has only access to nextcloud's files but not to other services on my server. My jails are managed via iocage.

My setup is as followed:
I have a "database jail" which runs PostgreSQL and OpenLDAP (user authentication), this jail is not reachable from the outside / public.
I have a "nextcloud jail" running Nextcloud on Apache. Nextcloud is able to access (via TCP) PostgreSQL and OpenLDAP in the "database jail" for user authentication and storing its (meta) data.
I also have a "svn jail" running a private Subversion Repository with webdav on Apache, this jail also can reach the OpenLDAP in the "database jail" for user auth via TCP.
Incoming http(s) requests to my server are first routet to my forth jail, the "proxy jail". Here I have a pound proxy running. Depending on the hostname/url of the incoming http(s) request,
pount routes the request to either the nextcloud or the svn jail.
For testing purposes I already have disabled the proxy jail and made the nextcloud jail reachable directly, without pound in the middle.
That didn't fix the problem, so I would assume that the issue has nothing to do with my "proxy jail"...

Here are my rules:

sh:
#!/bin/sh

#################################################
# configuration
################################################
fwcmd="/sbin/ipfw -q add"        # ipfw command
wan="em0"                        # the external interface (public internet)
loop="lo0"                        # loopback interface (local network for host only)
lan="lo1"                        # internal interface (local network for jails)
jumpNAT="skipto 65100"            # jump to NAT rule
jail_host="192.168.0.1"            # jail aliases
database_jail="192.168.0.2"
proxy_jail="192.168.0.3"
nextcloud_jail="192.168.0.4"
svn_jail="192.168.0.5"



################################################
# INIT
################################################

# flush out the list before we add any rules
/sbin/ipfw -q -f flush

# activate in-kernel NAT and define rules
/sbin/ipfw disable one_pass
/sbin/ipfw -q nat 1 config if ${wan} same_ports unreg_only reset \
    redirect_port tcp ${proxy_jail}:80 80 \
    redirect_port tcp ${proxy_jail}:443 443



################################################
# LOCAL traffic (rules 0-499)
################################################

# ALLOW anything within the loopback interface
${fwcmd} 00001 allow all from any to any via ${loop}

# ALLOW each jail to reach itself without restriction
${fwcmd} 00010 allow all from ${jail_host} to ${jail_host} via ${lan}
${fwcmd} 00011 allow all from ${database_jail} to ${database_jail} via ${lan}
${fwcmd} 00012 allow all from ${proxy_jail} to ${proxy_jail} via ${lan}
${fwcmd} 00013 allow all from ${nextcloud_jail} to ${nextcloud_jail} via ${lan}
${fwcmd} 00014 allow all from ${svn_jail} to ${svn_jail} via ${lan}



################################################
# NAT and existing entries in dynamic rules table
# (rules 500-999)
################################################

# reassemble inbound packets
${fwcmd} 00500 reass all from any to any in
# NAT any inbound packets
${fwcmd} 00501 nat 1 ip from any to any in via ${wan}
# allow packets having an existing entry in the dynamic rules table
${fwcmd} 00502 check-state



################################################
# OUTBOUND traffic (rules 1000-9999)
################################################

# ALLOW access to public DNS (see /etc/resolve.conf)
${fwcmd} 01000 ${jumpNAT} tcp from any to <dns1> 53 out via ${wan} setup keep-state
${fwcmd} 01001 ${jumpNAT} udp from any to <dns1> 53 out via ${wan} keep-state
${fwcmd} 01002 ${jumpNAT} tcp from any to <dns2> 53 out via ${wan} setup keep-state
${fwcmd} 01003 ${jumpNAT} udp from any to <dns2> 53 out via ${wan} keep-state

# ALLOW access to OpenNTP (see /usr/local/etc/ntpd.conf)
${fwcmd} 01010 ${jumpNAT} udp from any to any 123 out via ${wan} keep-state

# ALLOW nextcloud jail some outbound traffic:
# send mails
${fwcmd} 01050 ${jumpNAT} tcp from ${nextcloud_jail} to <mailserver> 465,993 out via ${wan} setup keep-state
# use HTTP / HTTPS connections
${fwcmd} 01051 ${jumpNAT} tcp from ${nextcloud_jail} to any 80,443 out via ${wan} setup keep-state

# ALLOW svn jail some outbound traffic
# send mails
${fwcmd} 01080 ${jumpNAT} tcp from ${svn_jail} to <mailserver> 465,993 out via ${wan} setup keep-state

# ALLOW traffic to services between jails (note: no NAT required)
# to database jail
${fwcmd} 01100 allow tcp from ${jail_host} to ${database_jail} 389,636,5432 out via ${lan} setup keep-state
${fwcmd} 01102 allow tcp from ${nextcloud_jail} to ${database_jail} 636,5432 out via ${lan} setup keep-state
${fwcmd} 01104 allow tcp from ${svn_jail} to ${database_jail} 636 out via ${lan} setup keep-state
# to proxy jail
${fwcmd} 01110 allow tcp from ${jail_host} to ${proxy_jail} 80,443 out via ${lan} setup keep-state
# to nextcloud jail
${fwcmd} 01130 allow tcp from ${jail_host} to ${nextcloud_jail} 80,443 out via ${lan} setup keep-state
${fwcmd} 01131 allow tcp from ${proxy_jail} to ${nextcloud_jail} 80,443 out via ${lan} setup keep-state
# to svn jail
${fwcmd} 01150 allow tcp from ${jail_host} to ${svn_jail} 80,443 out via ${lan} setup keep-state
${fwcmd} 01151 allow tcp from ${proxy_jail} to ${svn_jail} 80,443 out via ${lan} setup keep-state

# ALLOW each jail to reach the host's syslogd and exim (note: no NAT required)
${fwcmd} 01200 allow udp from 192.168.0.0/24 to ${jail_host} 514 out via ${lan} keep-state
${fwcmd} 01201 allow tcp from 192.168.0.0/24 to ${jail_host} 25 out via ${lan} setup keep-state

# ALLOW root user to reach anything
# (important for updates etc.)
${fwcmd} 01300 ${jumpNAT} tcp from me to any out via ${wan} setup keep-state uid root
${fwcmd} 01301 ${jumpNAT} udp from me to any out via ${wan} keep-state uid root
${fwcmd} 01302 ${jumpNAT} icmp from me to any out via ${wan} keep-state
# same for ipv6
${fwcmd} 01310 allow tcp from me6 to any out via ${wan} setup keep-state uid root
${fwcmd} 01311 allow udp from me6 to any out via ${wan} keep-state uid root
#${fwcmd} 01312 allow ipv6-icmp from me6 to any out via ${wan} keep-state

# DENY and log all other outbound connections
${fwcmd} 09999 deny log all from any to any out via ${wan}



################################################
# INBOUND traffic (rules 10000-19999)
################################################

# DENY all inbound traffic from non-routable reserved address spaces
${fwcmd} 10001 deny all from 192.168.0.0/16 to any in via ${wan}     #RFC 1918 private IP
${fwcmd} 10002 deny all from 172.16.0.0/12 to any in via ${wan}      #RFC 1918 private IP
${fwcmd} 10003 deny all from 10.0.0.0/8 to any in via ${wan}         #RFC 1918 private IP
${fwcmd} 10004 deny all from 127.0.0.0/8 to any in via ${wan}        #loopback
${fwcmd} 10005 deny all from 0.0.0.0/8 to any in via ${wan}          #loopback
${fwcmd} 10006 deny all from 169.254.0.0/16 to any in via ${wan}     #DHCP auto-config
${fwcmd} 10007 deny all from 192.0.2.0/24 to any in via ${wan}       #reserved for docs
${fwcmd} 10008 deny all from 204.152.64.0/23 to any in via ${wan}    #Sun cluster interconnect
${fwcmd} 10009 deny all from 224.0.0.0/3 to any in via ${wan}        #Class D & E multicast

# DENY public pings (only allow icmptype 0 if we ping stuff ourself)
${fwcmd} 10010 deny icmp from any to any in via ${wan} not icmptypes 0
${fwcmd} 10011 deny ipv6-icmp from any to any in via ${wan} not icmp6types 0

# DENY ident/ noise from routers
${fwcmd} 10020 deny tcp from any to any 113 in via ${wan}
${fwcmd} 10021 deny udp from any to any 520 in via ${wan}

# DENY all Netbios services
${fwcmd} 10030 deny tcp from any to any 137 in via ${wan}
${fwcmd} 10031 deny tcp from any to any 138 in via ${wan}
${fwcmd} 10032 deny tcp from any to any 139 in via ${wan}
${fwcmd} 10033 deny tcp from any to any 81 in via ${wan}

# DENY fragments
${fwcmd} 10040 deny all from any to any frag in via ${wan}

# DENY ACK packets that didn't match the dynamic rule table
${fwcmd} 10041 deny tcp from any to any established in via ${wan}

# DENY broadcasts and multicasts
${fwcmd} 10050 deny ip from any to 255.255.255.255
${fwcmd} 10051 deny ip from any to 224.0.0.0/24 in   

# DENY spoofing from outside
${fwcmd} 10060 deny ip from any to any not antispoof in via ${wan}
${fwcmd} 10061 deny all from any to 127.0.0.0/8 in via ${wan}
${fwcmd} 10062 deny all from any to ::1 in via ${wan}
${fwcmd} 10063 deny all from ::1 to any via ${wan}

# number 00015 reserved for bans from fail2ban
# ${fwcmd} 00015 deny all from <ban_ip> to me in via ${wan}

# ALLOW inbound SSH connections
${fwcmd} 11000 set 31 allow log tcp from any to me 22 in via ${wan} setup limit src-addr 3

# ALLOW inbound connections to services on jails
# http(s) requests routed via proxy_jail to nextcloud or svn jail
${fwcmd} 12000 ${jumpNAT} tcp from any to ${proxy_jail} 80,443 in via ${wan} setup keep-state

# DENY and log all other incoming connections
${fwcmd} 19999 deny log all from any to any in via ${wan}



################################################
## FINAL rules (>=65000)
################################################

# DENY and LOG all uncaptured messages on ANY interface
${fwcmd} 65000 deny log all from any to any

# ALLOW skipto location for outbound statefule rules
${fwcmd} 65100 nat 1 ip from 192.168.0.0/24 to any out via ${wan}
${fwcmd} 65101 allow ip from any to any

Kind regards,
Fool
 
But from a quick look into the handbook I would say yes, these are VNET jails:
Each jail has an own internal IP address and is isolated from all other jails. TCP based access is strictly controlled by ipfw rules.
The idea why I'm doing this is for an additional layer of security.

Sorry, I shouldn't have asked ... way past my experience, re jails especially. 'Tis I who feels foolish.

Hopefully all your well-presented detail will attract attention from someone who understands the jail isolation blocking contact here ...
 
Back
Top