Synopsis: relayd + httpd returns a 413 error only after reading entire
POST request body.
Category:       system user
Environment:
        System      : OpenBSD 7.7
Details : OpenBSD 7.7-beta (GENERIC.MP) #597: Sat Mar 15 20:15:56 MDT 2025
                         
dera...@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP

        Architecture: OpenBSD.amd64
        Machine     : amd64
Description:
        When a POST request using a crafted 1GB file is sent to httpd
        directly, httpd sends a 413 Payload Too Large error and aborts
        before the body has been sent. This is expected behavior to me.

        However, if that httpd is behind relayd, they seem to
        wait for the entire body to be received before issuing an
        error and aborting. I think this could potentially be a
        denial-of-service risk.

        I've tested on both 7.6 and the latest snapshot. This problem
        exists on both.
How-To-Repeat:
        Set up minimal working httpd and relayd configurations.
        
        # cp -p /etc/examples/{relayd,httpd}.conf /etc/

        # cat > /etc/httpd.conf <<EOF
server "default" {
        listen on 127.0.0.1 port 8080
        listen on ::1 port 8080
}
EOF

        # cat > /etc/relayd.conf <<EOF
http protocol "www" {
        pass
}

relay "www" {
        listen on 127.0.0.1 port www
        listen on ::1 port www
        protocol www
        forward to 127.0.0.1 port 8080
}
EOF

        Start the servers (via tmux panes or something).
        # relayd -dvvvvvv
        # httpd -dvvvvvv

        Create the crafted file.
        $ dd if=/dev/urandom of=bigfile.bin bs=1m count=1000

        Send the file via a POST request.
        $ curl -vF test=@bigfile.bin http://127.0.0.1/

        Notice how if the curl command interacts with httpd directly
        rather than going through relayd, the error is returned
        instantly.
        $ curl -vF test=@bigfile.bin http://127.0.0.1:8080/
Fix:
        The best workaround I found in my case was just to block
        everything except GET and HEAD via relayd. This is in the case
        of a static website, where only GET and HEAD are needed. But
        this does not actually fix the core issue.

        # cat > /etc/relayd.conf <<EOF
http protocol "www" {
        match request method "GET" tag "allowed_methods"
        match request method "HEAD" tag "allowed_methods"
        block
        pass tagged "allowed_methods"
}

relay "www" {
        listen on 127.0.0.1 port www
        listen on ::1 port www
        protocol www
        forward to 127.0.0.1 port 8080
}
EOF

dmesg:
OpenBSD 7.7-beta (GENERIC.MP) #597: Sat Mar 15 20:15:56 MDT 2025
    dera...@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP
real mem = 4160745472 (3967MB)
avail mem = 4008247296 (3822MB)
random: good seed from bootblocks
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 2.4 @ 0xfc100000 (12 entries)
bios0: vendor Xen version "4.17.5" date 02/16/2025
bios0: Xen HVM domU
acpi0 at bios0: ACPI 4.0
acpi0: sleep states S3 S4 S5
acpi0: tables DSDT FACP APIC HPET WAET SSDT SSDT
acpi0: wakeup devices
acpitimer0 at acpi0: 3579545 Hz, 32 bits
acpimadt0 at acpi0 addr 0xfee00000: PC-AT compat
ioapic0 at mainbus0: apid 1 pa 0xfec00000, version 11, 48 pins, remapped
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz, 1992.15 MHz, 06-8e-0c
cpu0: cpuid 1 edx=1fcbfbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT> ecx=f7fa3203<SSE3,PCLMUL,SSSE3,FMA3,CX16,PCID,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,AES,XSAVE,AVX,F16C,RDRAND,HV> cpu0: cpuid 7.0 ebx=9c27ab<FSGSBASE,TSC_ADJUST,BMI1,AVX2,SMEP,BMI2,ERMS,INVPCID,RDSEED,ADX,SMAP,CLFLUSHOPT> edx=bc000400<MD_CLEAR,IBRS,IBPB,STIBP,L1DF,SSBD>
cpu0: cpuid d.1 eax=f<XSAVEOPT,XSAVEC,XGETBV1,XSAVES>
cpu0: cpuid 80000001 edx=2c100800<NXE,PAGE1GB,RDTSCP,LONG> ecx=121<LAHF,ABM,3DNOWP>
cpu0: cpuid 80000007 edx=100<ITSC>
cpu0: msr 10a=c0a0023<IBRS_ALL,MDS_NO,FB_CLEAR,RRSBA,GDS_NO,RFDS_NO>
cpu0: 32KB 64b/line 8-way D-cache, 32KB 64b/line 8-way I-cache, 256KB 64b/line 4-way L2 cache, 8MB 64b/line 16-way L3 cache
cpu0: smt 0, core 0, package 0
mtrr: Pentium Pro MTRR support, 8 var ranges, 88 fixed ranges
cpu0: apic clock running at 100MHz
cpu1 at mainbus0: apid 2 (application processor)
cpu1: Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz, 1992.11 MHz, 06-8e-0c
cpu1: smt 0, core 1, package 0
acpihpet0 at acpi0: 62500000 Hz
acpiprt0 at acpi0: bus 0 (PCI0)
acpipci0 at acpi0 PCI0
acpicmos0 at acpi0
"PNP0F13" at acpi0 not configured
"PNP0303" at acpi0 not configured
acpicpu0 at acpi0: C1(@1 halt!)
acpicpu1 at acpi0: C1(@1 halt!)
pvbus0 at mainbus0: Xen 4.17
xen0 at pvbus0: features 0x52305, 2048 grant table frames, event channel 1
"vbd" at xen0: device/vbd/2048 not configured
"vbd" at xen0: device/vbd/2064 not configured
"vbd" at xen0: device/vbd/2080 not configured
xnf0 at xen0 backend 5 channel 6: address 00:16:3e:5e:6c:00
pci0 at mainbus0 bus 0
pchb0 at pci0 dev 0 function 0 "Intel 82441FX" rev 0x02
pcib0 at pci0 dev 1 function 0 "Intel 82371SB ISA" rev 0x00
pciide0 at pci0 dev 1 function 1 "Intel 82371SB IDE" rev 0x00: DMA, channel 0 wired to compatibility, channel 1 wired to compatibility
pciide0: channel 0 disabled (no drives)
pciide0: channel 1 disabled (no drives)
piixpm0 at pci0 dev 1 function 3 "Intel 82371AB Power" rev 0x03: SMBus disabled
xspd0 at pci0 dev 2 function 0 "XenSource Platform Device" rev 0x01
siop0 at pci0 dev 3 function 0 "Symbios Logic 53c895A" rev 0x00: apic 1 int 28, using 8K of on-board RAM
scsibus1 at siop0: 16 targets, initiator 7
sd0 at scsibus1 targ 0 lun 0: <QEMU, QEMU HARDDISK, 2.5+>
sd0: 81920MB, 512 bytes/sector, 167772160 sectors, thin
sd1 at scsibus1 targ 1 lun 0: <QEMU, QEMU HARDDISK, 2.5+>
sd1: 2048MB, 512 bytes/sector, 4194304 sectors, thin
sd2 at scsibus1 targ 2 lun 0: <QEMU, QEMU HARDDISK, 2.5+>
sd2: 10240MB, 512 bytes/sector, 20971520 sectors, thin
vga1 at pci0 dev 4 function 0 "Bochs VGA" rev 0x02
wsdisplay0 at vga1 mux 1: console (80x25, vt100 emulation)
wsdisplay0: screen 1-5 added (80x25, vt100 emulation)
ehci0 at pci0 dev 5 function 0 "Intel 82801DB USB" rev 0x10: apic 1 int 39
usb0 at ehci0: USB revision 2.0
uhub0 at usb0 configuration 1 interface 0 "Intel EHCI root hub" rev 2.00/1.00 addr 1
isa0 at pcib0
isadma0 at isa0
fdc0 at isa0 port 0x3f0/6 irq 6 drq 2
pckbc0 at isa0 port 0x60/5 irq 1 irq 12
pckbd0 at pckbc0 (kbd slot)
wskbd0 at pckbd0: console keyboard, using wsdisplay0
pms0 at pckbc0 (aux slot)
wsmouse0 at pms0 mux 0
pcppi0 at isa0 port 0x61
spkr0 at pcppi0
uhidev0 at uhub0 port 1 configuration 1 interface 0 "QEMU QEMU USB Tablet" rev 2.00/0.00 addr 2
uhidev0: iclass 3/0
ums0 at uhidev0: 3 buttons, Z dir
wsmouse1 at ums0 mux 0
vscsi0 at root
scsibus2 at vscsi0: 256 targets
softraid0 at root
scsibus3 at softraid0: 256 targets
root on sd0a (e39bc959e5c5c350.a) swap on sd0b dump on sd0b
fd0 at fdc0 drive 1: density unknown

usbdevs:
Controller /dev/usb0:
addr 01: 8086:0000 Intel, EHCI root hub
         high speed, self powered, config 1, rev 1.00
         driver: uhub0
addr 02: 0627:0001 QEMU, QEMU USB Tablet
         high speed, power 100 mA, config 1, rev 0.00, iSerial 42
         driver: uhidev0

Reply via email to