Nextcloud seems to need http/1.1?

Support intro

Sorry to hear you’re facing problems. :slightly_frowning_face:

The community help forum (help.nextcloud.com) is for home and non-enterprise users. Support is provided by other community members on a best effort / “as available” basis. All of those responding are volunteering their time to help you.

If you’re using Nextcloud in a business/critical setting, paid and SLA-based support services can be accessed via portal.nextcloud.com where Nextcloud engineers can help ensure your business keeps running smoothly.

Getting help

In order to help you as efficiently (and quickly!) as possible, please fill in as much of the below requested information as you can.

Before clicking submit: Please check if your query is already addressed via the following resources:

(Utilizing these existing resources is typically faster. It also helps reduce the load on our generous volunteers while elevating the signal to noise ratio of the forums otherwise arising from the same queries being posted repeatedly).

Some or all of the below information will be requested if it isn’t supplied; for fastest response please provide as much as you can. :heart:

The Basics

  • Nextcloud Server version (e.g., 29.x.x):

    • updated yesterday to spring 2026-2
  • Operating system and version (e.g., Ubuntu 24.04):

    • RASBIAN latest
    • Web server and version (e.g, Apache 2.4.25):
    • NGINX

    Reverse proxy and version _(e.g. nginx 1.27.2)

    • latest

    PHP version (e.g, 8.3):

    • 8.5
  • Is this the first time you’ve seen this error? (Yes / No):

    • replace me
  • When did this problem seem to first start?

    • After I disabled http/1.1 in iptables
  • Installation method (e.g. AlO, NCP, Bare Metal/Archive, etc.)

    • today
  • Are you using CloudfIare, mod_security, or similar? (Yes / No)

    • IPTABLES

Summary of the issue you are facing:

I have A LOT of http/1.1 traffic trying to hack or crawl my websites.
I disabled port 80 and only allowed https. Enabled within NGINX http2 and http3. But still my logs where flooded with http/1.1 requests. After disabling http/1.1 through iptables, nextcloud server is not responding and time out’s! When removing iptables rule, all is fine, except I again get so much http/1.1 garbage.

Steps to replicate it (hint: details matter!):

  1. added;
    sudo iptables -A INPUT -p udp --dport 443 -j DROP # BLock ALL http:/1.1 access on port 443

Log entries

None, fails to connect by iptables blockking all http/1.1 443 traffic

Nextcloud

Please provide the log entries from your Nextcloud log that are generated during the time of problem (via the Copy raw option from Administration settings->Logging screen or from your nextcloud.log located in your data directory). Feel free to use a pastebin/gist service if necessary.

PASTE HERE

Web Browser

If the problem is related to the Web interface, open your browser inspector Console and Network tabs while refreshing (reloading) and reproducing the problem. Provide any relevant output/errors here that appear.

Any

Web server / Reverse Proxy

The output of your Apache/nginx/system log in /var/log/____:

PASTE HERE

Configuration

Nextcloud

The output of occ config:list system or similar is best, but, if not possible, the contents of your config.php file from /path/to/nextcloud is fine (make sure to remove any identifiable information!):

{
    "system": {
        "instanceid": "***REMOVED SENSITIVE VALUE***",
        "passwordsalt": "***REMOVED SENSITIVE VALUE***",
        "secret": "***REMOVED SENSITIVE VALUE***",
        "trusted_domains": [
            "nextcloud.nl1106.eu"
        ],
        "datadirectory": "***REMOVED SENSITIVE VALUE***",
        "dbtype": "mysql",
        "version": "34.0.2.1",
        "overwrite.cli.url": "https:\/\/nextcloud.nl1106.eu",
        "dbname": "***REMOVED SENSITIVE VALUE***",
        "dbhost": "***REMOVED SENSITIVE VALUE***",
        "dbtableprefix": "oc_",
        "debug": false,
        "mysql.utf8mb4": true,
        "dbuser": "***REMOVED SENSITIVE VALUE***",
        "dbpassword": "***REMOVED SENSITIVE VALUE***",
        "installed": true,
        "log_type_audit": "syslog",
        "syslog_tag_audit": "Nextcloud",
        "logfile_audit": "",
        "config_preset": 7,
        "mail_smtpmode": "sendmail",
        "mail_sendmailmode": "smtp",
        "mail_from_address": "***REMOVED SENSITIVE VALUE***",
        "mail_domain": "***REMOVED SENSITIVE VALUE***",
        "mail_smtphost": "***REMOVED SENSITIVE VALUE***",
        "mail_smtpport": "993",
        "maintenance": false,
        "mail_smtpsecure": "ssl",
        "mail_smtpauth": true,
        "updater.release.channel": "stable",
        "app_install_overwrite": {
            "1": "groupfolders",
            "2": "mail_roundcube",
            "3": "backup"
        },
        "theme": "",
        "loglevel": 0,
        "maintenance_window_start": 0,
        "updater.secret": "***REMOVED SENSITIVE VALUE***",
        "default_phone_region": "031",
        "memcache.local": "\\OC\\Memcache\\APCu",
        "memcache.locking": "\\OC\\Memcache\\Redis",
        "redis": {
            "host": "***REMOVED SENSITIVE VALUE***",
            "port": 6379
        },
        "serverid": "1"
    },
    "apps": {
        "activity": {
            "enabled": "yes",
            "installed_version": "7.0.0",
            "types": "filesystem"
        },
        "app_api": {
            "enabled": "no",
            "installed_version": "34.0.0",
            "types": ""
        },
        "appointments": {
            "enabled": "no",
            "hk": "5f2feb468e4c95235b4efd171edd48a11a7ee6ce5f62d1de9228ef6f214b509c",
            "installed_version": "2.7.4",
            "tiv": "ebdf8d8001428f83db9de27cbffdbdc0",
            "types": "dav"
        },
        "appstore": {
            "enabled": "yes",
            "installed_version": "1.0.0",
            "types": ""
        },
        "backgroundjob": {
            "lastjob": "90312896426418177"
        },
        "backup": {
            "allow_weekday": "0",
            "cron_enabled": "1",
            "delay_full_rp": "24",
            "delay_partial_rp": "3",
            "enabled": "yes",
            "installed_version": "1.4.0",
            "mockup_date": "1784418177",
            "pack_backup": "1",
            "pack_compress": "1",
            "pack_encrypt": "1",
            "store_items": "3",
            "store_items_external": "5",
            "time_slots": "23-5",
            "types": ""
        },
        "bruteforcesettings": {
            "enabled": "yes",
            "installed_version": "7.0.0",
            "types": ""
        },
        "calendar": {
            "enabled": "[\"eCar Gaasperdam\",\"eCar Chauffeurs\",\"Klanten\",\"admin\",\"guest_app\"]",
            "installed_version": "6.5.2",
            "types": ""
        },
        "calendar_resource_management": {
            "enabled": "yes",
            "installed_version": "0.12.1",
            "types": "prevent_group_restriction"
        },
        "circles": {
            "enabled": "yes",
            "installed_version": "34.0.0",
            "loopback_tmp_scheme": "https",
            "maintenance_run": "0",
            "maintenance_update": "{\"3\":1780318657,\"2\":1780318657,\"1\":1780318657}",
            "migration_22": "1",
            "migration_run": "0",
            "types": "filesystem,dav"
        },
        "cloud_federation_api": {
            "enabled": "yes",
            "installed_version": "1.18.0",
            "types": "filesystem"
        },
        "cms_pico": {
            "enabled": "no",
            "installed_version": "1.0.21",
            "types": "filesystem"
        },
        "comments": {
            "enabled": "yes",
            "installed_version": "1.24.0",
            "types": "logging"
        },
        "contacts": {
            "enabled": "yes",
            "installed_version": "8.7.5",
            "types": "dav"
        },
        "contactsinteraction": {
            "enabled": "yes",
            "installed_version": "1.15.0",
            "types": "dav"
        },
        "core": {
            "backgroundjobs_mode": "cron",
            "emailTestSuccessful": "1",
            "installedat": "1771429814.9842",
            "lastcron": 1784142226,
            "lastupdateResult": "[]",
            "lastupdatedat": 1785265165,
            "mail_providers_enabled": false,
            "metadataGenerationDone": true,
            "moveavatarsdone": "yes",
            "newUser.sendEmail": false,
            "previewMovedDone": true,
            "previewsCleanedUp": "1",
            "public_files": "files_sharing\/public.php",
            "updater.secret.created": 1785264561,
            "vendor": "nextcloud",
            "files_metadata": {
                "photos-original_date_time": {
                    "value": null,
                    "type": "int",
                    "etag": "",
                    "indexed": true,
                    "editPermission": 0
                },
                "photos-size": {
                    "value": null,
                    "type": "array",
                    "etag": "",
                    "indexed": false,
                    "editPermission": 0
                },
                "photos-exif": {
                    "value": null,
                    "type": "array",
                    "etag": "",
                    "indexed": false,
                    "editPermission": 0
                },
                "photos-ifd0": {
                    "value": null,
                    "type": "array",
                    "etag": "",
                    "indexed": false,
                    "editPermission": 0
                },
                "blurhash": {
                    "value": null,
                    "type": "string",
                    "etag": "24fc61679da8f9988d9c9999806cd177",
                    "indexed": false,
                    "editPermission": 0
                },
                "photos-gps": {
                    "value": null,
                    "type": "array",
                    "etag": "",
                    "indexed": false,
                    "editPermission": 0
                }
            },
            "oc.integritycheck.checker": {
                "spreed": {
                    "FILE_MISSING": {
                        "templates\/index.php": {
                            "expected": "e1ea54dbc813692dd1c623730da0112bca2d2505ddb26abc38853cdd472b99be28c8f48b89b3d5206e2d6b2411d297db7eb276d9cdb93fd044c2eccb0d240382",
                            "current": ""
                        }
                    }
                },
                "mail_roundcube": {
                    "FILE_MISSING": {
                        "templates\/settings\/admin.php": {
                            "expected": "05b865a206fa8b1a99658cc154e1087c0f6a20bd90581dcbdebfe58d2be1c6c54eda74763c2ea3305c6e6aa78f0ecca5665cdc34ba9e21f6ed1bfd4d3f4453d9",
                            "current": ""
                        }
                    }
                },
                "guests": {
                    "FILE_MISSING": {
                        "templates\/settings\/admin.php": {
                            "expected": "2723178bac042998eefa5c865f1684b5589c69e888942375aa4a6dd9a9f28b64291585b0f743ec984c1bd7b02cb6e20bdda827566c11cdac880e9d8768dd5d1a",
                            "current": ""
                        }
                    }
                },
                "whiteboard": {
                    "FILE_MISSING": {
                        "templates\/admin.php": {
                            "expected": "1c1927f7c844a16a6bb082e456e1f67b36297e009f24e2cc6a47a9759eda35536feb8da8a6ce86cf99e2f8b4cd2033789d61e3b9b8377730706120fe8de402b6",
                            "current": ""
                        }
                    }
                }
            }
        },
        "cospend": {
            "enabled": "no",
            "installed_version": "4.0.2",
            "types": ""
        },
        "dashboard": {
            "enabled": "yes",
            "installed_version": "7.14.0",
            "types": ""
        },
        "dav": {
            "buildCalendarReminderIndex": "yes",
            "buildCalendarSearchIndex": "yes",
            "builtSocialSearchIndex": true,
            "checked_for_classified_activity": true,
            "chunks_migrated": "1",
            "enabled": "yes",
            "generateBirthdayCalendar": "yes",
            "hasCustomDefaultContact": false,
            "installed_version": "1.39.0",
            "regeneratedBirthdayCalendarsForYearFix": "yes",
            "types": "filesystem"
        },
        "deck": {
            "enabled": "yes",
            "installed_version": "1.18.3",
            "types": "dav"
        },
        "federatedfilesharing": {
            "enabled": "yes",
            "installed_version": "1.24.0",
            "types": ""
        },
        "federation": {
            "enabled": "yes",
            "installed_version": "1.24.0",
            "types": "authentication"
        },
        "files": {
            "enabled": "yes",
            "installed_version": "2.6.0",
            "mimetype_version": "33.0.3.2",
            "types": "filesystem"
        },
        "files_downloadlimit": {
            "enabled": "yes",
            "installed_version": "5.2.0",
            "types": ""
        },
        "files_lock": {
            "enabled": "yes",
            "installed_version": "34.0.1",
            "types": "filesystem,dav"
        },
        "files_pdfviewer": {
            "enabled": "yes",
            "installed_version": "7.0.0-dev.0",
            "types": ""
        },
        "files_reminders": {
            "enabled": "yes",
            "installed_version": "1.7.0",
            "types": ""
        },
        "files_retention": {
            "enabled": "[\"admin\"]",
            "installed_version": "5.0.0",
            "types": ""
        },
        "files_sharing": {
            "enabled": "yes",
            "installed_version": "1.26.0",
            "types": "filesystem"
        },
        "files_trashbin": {
            "enabled": "yes",
            "installed_version": "1.24.0",
            "types": "filesystem,dav"
        },
        "files_versions": {
            "enabled": "yes",
            "installed_version": "1.27.0",
            "types": "filesystem,dav"
        },
        "firstrunwizard": {
            "enabled": "yes",
            "installed_version": "7.0.0-dev.0",
            "types": ""
        },
        "groupfolders": {
            "checked_for_incorrect_storage_for_trash_items": true,
            "enabled": "yes",
            "installed_version": "22.0.5",
            "types": "filesystem,dav"
        },
        "guests": {
            "enabled": "yes",
            "installed_version": "4.8.0",
            "types": "authentication"
        },
        "logreader": {
            "enabled": "yes",
            "installed_version": "7.0.0",
            "types": "logging"
        },
        "lookup_server_connector": {
            "enabled": "yes",
            "installed_version": "1.22.0",
            "types": "authentication"
        },
        "mail": {
            "enabled": "yes",
            "installed_version": "5.10.10",
            "types": ""
        },
        "mail_roundcube": {
            "emailAddressChoice": "userIdEmail",
            "enabled": "no",
            "installed_version": "1.2.2",
            "types": ""
        },
        "nextcloud_announcements": {
            "enabled": "yes",
            "installed_version": "6.0.0",
            "pub_date": "Thu, 24 Oct 2019 00:00:00 +0200",
            "types": "logging"
        },
        "notes": {
            "enabled": "yes",
            "installed_version": "6.0.1",
            "types": ""
        },
        "notifications": {
            "enabled": "yes",
            "installed_version": "7.0.0-dev.1",
            "setting_batchtime": "0",
            "sound_notification": "yes",
            "sound_talk": "no",
            "types": "logging",
            "webpush_vapid_privkey": "***REMOVED SENSITIVE VALUE***",
            "webpush_vapid_pubkey": "BOefdMnQlDN4VBLC_iWI-QE1OfFDSJABRtr49x8DWcJu4AXX6T1wcxKOY2OUfGLgJuolryc8JaMADhY_CTNgilI"
        },
        "oauth2": {
            "enabled": "yes",
            "installed_version": "1.22.0",
            "types": "authentication"
        },
        "office": {
            "enabled": "yes",
            "installed_version": "1.0.0",
            "types": ""
        },
        "password_policy": {
            "enabled": "yes",
            "installed_version": "6.0.0-dev.0",
            "minLength": "7",
            "types": "authentication"
        },
        "photos": {
            "enabled": "yes",
            "installed_version": "7.0.0",
            "lastPlaceMappedUser": "nubro01",
            "lastPlaceMappingDone": "true",
            "types": "authentication,dav"
        },
        "privacy": {
            "enabled": "yes",
            "installed_version": "6.0.0-dev.1",
            "readableLocation": "nl",
            "types": ""
        },
        "profile": {
            "enabled": "yes",
            "installed_version": "1.3.0",
            "types": ""
        },
        "provisioning_api": {
            "enabled": "yes",
            "installed_version": "1.24.0",
            "types": "prevent_group_restriction"
        },
        "recommendations": {
            "enabled": "yes",
            "installed_version": "7.0.0",
            "types": ""
        },
        "related_resources": {
            "enabled": "yes",
            "installed_version": "5.0.0-dev.0",
            "types": ""
        },
        "richdocuments": {
            "disable_certificate_verification": "yes",
            "enabled": "yes",
            "installed_version": "11.1.0",
            "types": "filesystem,prevent_group_restriction",
            "wopi_url": ""
        },
        "serverinfo": {
            "cached_count_appdata_files": 1385,
            "cached_count_filecache": 1752,
            "cached_count_storages": 6,
            "enabled": "yes",
            "installed_version": "6.0.0",
            "size_appdata_storage": 5166833,
            "types": ""
        },
        "settings": {
            "enabled": "yes",
            "installed_version": "1.17.0",
            "types": ""
        },
        "sharebymail": {
            "enabled": "yes",
            "installed_version": "1.24.0",
            "types": "filesystem"
        },
        "spreed": {
            "default_group_notification": 2,
            "enabled": "no",
            "installed_version": "24.0.1",
            "project_access_invalidated": "1",
            "signaling_token_privkey_es256": "***REMOVED SENSITIVE VALUE***",
            "signaling_token_pubkey_es256": "***REMOVED SENSITIVE VALUE***",
            "types": "dav,prevent_group_restriction"
        },
        "support": {
            "SwitchUpdaterServerHasRun": "yes",
            "enabled": "yes",
            "installed_version": "6.0.0",
            "types": "session"
        },
        "survey_client": {
            "enabled": "yes",
            "installed_version": "6.0.0-dev.0",
            "never_again": true,
            "types": ""
        },
        "systemtags": {
            "enabled": "yes",
            "installed_version": "1.24.0",
            "types": "logging"
        },
        "text": {
            "enabled": "yes",
            "installed_version": "8.0.0",
            "types": "dav"
        },
        "theming": {
            "cachebuster": 6,
            "enabled": "yes",
            "installed_version": "2.9.0",
            "logoDimensions": "266x260",
            "logoMime": "image\/png",
            "logoheaderMime": "image\/png",
            "name": "eCar Gaasperdam",
            "slogan": "***REMOVED SENSITIVE VALUE***",
            "types": "logging",
            "url": "***REMOVED SENSITIVE VALUE***"
        },
        "twofactor_backupcodes": {
            "enabled": "yes",
            "installed_version": "1.23.0",
            "types": ""
        },
        "twofactor_totp": {
            "enabled": "yes",
            "installed_version": "16.0.0",
            "types": ""
        },
        "twofactor_webauthn": {
            "enabled": "yes",
            "installed_version": "2.7.0",
            "types": ""
        },
        "updatenotification": {
            "enabled": "yes",
            "installed_version": "1.24.0",
            "types": "",
            "update_check_errors": 0
        },
        "user_status": {
            "enabled": "yes",
            "installed_version": "1.14.0",
            "types": ""
        },
        "viewer": {
            "enabled": "yes",
            "installed_version": "7.0.0-dev.0",
            "types": ""
        },
        "weather_status": {
            "enabled": "no",
            "installed_version": "1.14.0",
            "types": ""
        },
        "webhook_listeners": {
            "enabled": "yes",
            "installed_version": "1.6.0",
            "types": "filesystem"
        },
        "whiteboard": {
            "enabled": "no",
            "installed_version": "1.5.9",
            "types": ""
        },
        "workflowengine": {
            "enabled": "yes",
            "installed_version": "2.16.0",
            "types": "filesystem"
        }
    }
}

Apps

The output of occ app:list (if possible).

Tips for increasing the likelihood of a response

  • Use the preformatted text formatting option in the editor for all log entries and configuration output.
  • If screenshots are useful, feel free to include them.
    • If possible, also include key error output in text form so it can be searched for.
  • Try to edit log output only minimally (if at all) so that it can be ran through analyzers / formatters by those trying to help you.

Hi @nubro01,

a few things are getting mixed up here, and one of them explains the timeouts directly.

You cannot filter HTTP versions with iptables. iptables and nftables work at the IP/TCP/UDP layer. The HTTP version is an application-layer detail, and over HTTPS it lives inside the encrypted TLS stream, so the packet filter never even sees whether a request is “HTTP/1.1” or anything else. There is no rule that can match on it.

What your rule actually did:

sudo iptables -A INPUT -p udp --dport 443 -j DROP

-p udp --dport 443 is QUIC, i.e. HTTP/3[1]. You dropped the exact protocol you had just enabled, not HTTP/1.1. HTTP/1.1 runs over TCP/443 and stayed wide open. And because you used DROP (silent) rather than REJECT, any HTTP/3-capable client that had already learned your server speaks h3 (cached Alt-Svc) sits there waiting for UDP answers that never come, until it times out and maybe falls back to TCP. That is your “server not responding / timeouts”. Remove the rule and h3 works again, which is exactly what you saw.

HTTP/1.1 is not attack traffic. It is a current, perfectly normal protocol, and a lot of legitimate clients speak it, including Nextcloud’s own:

  • the Desktop client uses HTTP/1.1 by default; HTTP/2 is opt-in, you have to set the OWNCLOUD_HTTP2_ENABLED environment variable to 1[2],
  • and unless I am much mistaken, the Android client still sends its WebDAV file transfers over HTTP/1.1 on purpose. The sync path in the client library is pinned to it (OwnCloudClient.java, setParameter(PARAM_PROTOCOL_VERSION, HttpVersion.HTTP_1_1))[3], and “full HTTP/2 support” has been an open issue since 2018, one I filed myself and which is still open today[4]. So a server that only offers HTTP/2 works only because it falls back to 1.1 for the app.

So if you ever managed to block HTTP/1.1, you would break your own clients. That is why it looks like “Nextcloud needs HTTP/1.1”: it does, in the sense that its clients use it.

Check which log you are actually reading. With a reverse proxy in front, the line you see may be the proxy-to-backend hop, not the visitor. nginx proxy_pass talks HTTP/1.0 to the upstream unless you set proxy_http_version 1.1;, so a good chunk of the “1.0”/“1.1” in your backend log can be your own proxy rather than a crawler. Look at $server_protocol on the edge (the nginx that terminates TLS) to see what visitors really negotiate.

Blocking bots/crawlers is layer-7 work, not firewall work. The tools that actually help:

  • fail2ban on the access log (ban on rate or on known-bad patterns),

  • mod_security or another WAF,

  • nginx rate limiting (limit_req),

  • and if you want to throw away genuinely ancient junk, drop HTTP/1.0 (not 1.1) at the application layer, e.g. on the edge server:

    if ($server_protocol = HTTP/1.0) { return 444; }
    

    HTTP/1.0 is a reasonable “this is junk” signal; HTTP/1.1 is not, because your real clients use it.

Short version: remove the UDP/443 drop, leave HTTP/1.1 alone, and move the filtering to layer 7.

To give you something concrete, it would help to know:

  • Which log shows the “1.1” traffic, the edge nginx or the backend? A couple of raw lines would settle it.
  • Is the reverse proxy a separate hop from the nginx that terminates TLS, and what proxy_http_version is set on it?
  • What are you actually trying to stop, specific crawlers, IP ranges, or paths? That decides the right tool.

h.t.h.


ernolf


References:


  1. HTTP/3 (QUIC) for Nextcloud and Apache — Complete Guide ↩︎

  2. Nextcloud Client and Http2 support - #6 by ernolf ↩︎

  3. android-library/library/src/main/java/com/owncloud/android/lib/common/OwnCloudClient.java at 4b16ffab94e087925e6390aee889c47cd1f5b2c0 · nextcloud/android-library · GitHub ↩︎

  4. Full HTTP/2 support · Issue #2681 · nextcloud/android · GitHub ↩︎

I am trying to stop all 426 errors being logged to my access.log.
I have several rules whithin NGINX server to stop http/1.1 traffic, also in my 3 Nextcloud test servers.
With that all seems to work fine, only my logs are filling up with http/1.1 426 status codes, so blocking http/1.1 seems to work. Next cloud functions normally until I blocked udp and you explained that I need that for Quic, I already removed it and replaced it with sudo iptables -A INPUT -p tcp --dport 443 -j DROP, but that also did not let NEXTCLOUD function. Disabled this rule, again floods my logs, but it seems this is how the internet functions. All that crap from AI, Google, Microsoft and Amazon and all those wierdo’s trying to get into my unimportant websites with trying all kinds of php script naming. If they would only honour robots.txt then…

I removed the iptables rule and nextcloud reacted again correctly. Checking the access, log I noticed none http/1.1 traffic from Nextcloud, only the expected http/2.0 traffic, so I still wonder what logic, besides when you use Android clients, lies behind the fact that you cannot disable http/1.1 traffic this way.

The 426 is the key detail, and it points the other way from where you are aiming.

426 “Upgrade Required” is not incoming attack traffic. It is the answer your own nginx sends when it refuses an HTTP/1.1 request and tells the client to upgrade. So your access log filling with “http/1.1 … 426” is your server rejecting HTTP/1.1 over and over. The rule that emits the 426 is the cause of that noise, not a defense against it. Remove the HTTP/1.1 rejection and those lines disappear.

And a good share of what gets rejected there are your own clients. As I noted above, the Desktop client is HTTP/1.1 by default and the Android sync path is pinned to HTTP/1.1, so they get 426’d too. That is exactly the “seems to need HTTP/1.1” you started with.

On the firewall rule:

sudo iptables -A INPUT -p tcp --dport 443 -j DROP

that drops every HTTPS packet on the box, HTTP/1.1, HTTP/2, all of it, for every client. iptables has no idea which HTTP version is inside, it cannot see it, because it is encrypted inside TLS. If that rule seems to “help”, it is only dropping something wholesale, not selecting HTTP/1.1.

The thing you actually want gone, scanners that ignore robots.txt, does not correlate with the HTTP version at all. robots.txt is advisory anyway, and a scanner that ignores it will happily speak HTTP/2 as well, so version-blocking both fails to stop them and keeps hurting your real clients. That job belongs to:

  • fail2ban on the access log (ban an IP by request rate, or when it hits known-bad paths),
  • nginx rate limiting (limit_req),
  • mod_security or another WAF,
  • and blocking by user-agent, path, ASN or country where the pattern is clear.

If the only thing bothering you is the 426 noise and not the bots themselves, the fix is to stop emitting 426 (serve HTTP/1.1 normally), or at most access_log off for that one rejection, never a firewall rule that can take the whole site down.

To actually help instead of guessing, I still need three things:

  • one raw access.log line of the traffic you want gone: remote IP, method, path, user-agent, status,
  • whether this is the edge nginx (TLS termination) or a backend behind the reverse proxy, and what $server_protocol shows there,
  • the exact nginx rule that returns the 426.

With those, this is a five-minute fail2ban or map rule instead of a firewall that keeps knocking your own site offline.

h.t.h.


ernolf

While @ernolf’s explanation is very thorough, here’s a slightly simplified version. :wink:

With a packet filter such as iptables, you can filter traffic based on things like IP addresses, ports, and TCP/UDP protocols. What you can’t do is selectively allow or block specific application-layer protocols or HTTP versions. Packet filters operate at the network and transport layers, whereas protocols such as HTTP are handled at the application layer.

As a result, if you allow TCP port 443, clients can send whatever they want over it: HTTP/1.1, HTTP/2 or even completely different protocols, such as SSH. What happens next depends entirely on the application listening on port 443.

If it’s an NGINX web server, it will process valid HTTP requests, but other protocols such as SSH will simply fail because NGINX doesn’t understand them.

You can disable HTTP/1.1 support in NGINX, but that doesn’t necessarily stop such requests from reaching the server or being logged (not entierly sure about that, though).

It’s also not necessarly a good idea unless you’re absolutely certain that all of your clients support HTTP/2. In practice, clients and the server negotiate the highest HTTP version they both support, so HTTP/2-capable clients will use HTTP/2 automatically, while older clients will simply fall back to HTTP/1.1.

Thanks, this cleared things up, never realised I was myself creating those entries with my server statement.
I removed all and indeed no more 426 error’s. Stil Google is flooding with all kinds of strange get’s.
I have 8 unimportant website running on a raspberry pi 5 and I still want to know what is going on.
So I wrote a small Rust program to investigate which ip address are accessing my pi, so if it is a range, like Google I can use iptables to drop them :-1:
Thanks again. I learned someting again and that at 74 :wink:

use std::collections::HashMap;
use std::fs::File;
use std::env;

use std::io::{self, BufRead};

fn main() -> io::Result<()> {
// Collect command-line arguments
let args: Vec = env::args().collect();
if args.len() < 2 {
println!("Usage: cargo run <file_path>");
return Ok(());
}
let mut ip_count = HashMap::new();


for file_path in &args[1..] {
    // Attempt to open the file
	println!("Reading file: {}", file_path);
    let file = File::open(file_path)?;
    let reader = io::BufReader::new(file);

	for line in reader.lines() {
		let line = line?;
		// Extract the IP address (assuming it's the first word in each line)
		if let Some(ip) = line.split_whitespace().next() {
			*ip_count.entry(ip.to_string()).or_insert(0) += 1;
		}
	}
}

// Sort and print the results
let mut sorted_ips: Vec<_> = ip_count.iter().collect();
sorted_ips.sort_by(|a, b| b.0.cmp(a.0)); // Sort by count descending

for (ip, count) in sorted_ips {
	if *count as i32 > 9 {	
		println!("sudo iptables -A INPUT -s {} -j DROP #: {}", ip, count);
	}
}
Ok(())}

Honestly, @ernolf pointed you to fail2ban, which is a program already doing such things. People tested this, it works with in different environments, can be easily adjusted to different use-cases. And people share configuration examples, it works for ipv4/ipv6, blocks are perhaps only temporary, …

With your own program you’ll find many issues the hard way. Have fun writing code, for security/reliability-related topics, I’d rather use well-tested code.

a.0 and b.0 don’t take the ip address, so you sort everything by ip address and not count?

And on a Linux shell, you can do this with a one-liner (no need to write code and compile it):

awk '{print $1}' access.log | sort | uniq -c | awk '$1 > 9 {print "sudo iptables -A INPUT -s "$2" -j DROP #: "$1}'

And be careful not to block yourself out of your server!

The tool you wrote, and the goal behind it (block whole ranges like Google), is exactly what fail2ban already does, and it covers the range part too, which is the piece you are hand-rolling.

Beyond the sorting bug @tflidd already caught, two things about emitting iptables -A INPUT -s IP -j DROP will bite you:

  • The threshold of “more than 9 requests” is far below normal traffic. A single browser opening one page pulls dozens of assets at once, a Nextcloud desktop or mobile sync is many requests in a burst, and a legitimate crawler passes 9 easily. At > 9 you ban yourself and your real clients, not just scanners. fail2ban’s findtime/maxretry let you say “9 hits in 10 seconds”, which is an actual abuse signal instead of a raw total.
  • The rules never expire. -A INPUT -s IP -j DROP stays forever and the list only grows, with no unban when that address turns out to be a dynamic IP a real user gets next week. fail2ban ages bans out (bantime) and persists them across restarts for you.

On blocking ranges specifically: you do not want one DROP rule per IP for a /16, you want the whole range as a single entry. With nftables that is nft add element ... { 8.8.0.0/16 } into a named set with interval flags, one atomic rule for the entire block. I wrote up a working fail2ban setup that does precisely this, parameterising the CIDR mask at the jail level, so you feed it a plain list of ranges in CIDR notation and each is blocked as one unit: Exception HMAC does not match - #39 by ernolf

That is the by-hand range-blocking you are building, with expiry and persistence for free.

One caveat on Google: if those sites should stay findable, blocking Googlebot’s ranges deindexes them. If they are throwaway, that is fine, but then not serving them at all is simpler than curating a Google blocklist.

And for the scanner noise on Nextcloud itself, fail2ban on the access log (ban on request rate or on known-bad probe paths) is still the right tool, as covered above.

Ever since I put my Nextcloud behind a Caddy reverse proxy, I haven’t seen a single HMAC entry in the Nextcloud logs anymore. I still see all kinds of bots in Caddy’s logs looking for things like /wp-admin, but who cares? :wink:

And yes, Googlebot can be a bit annoying, but it doesn’t cause any actual issues, especially not with Netxlcoud. I mean, these bots are not stupid. They don’t repeatedly hammer a login page 100 times a day, at least they don’t on my setup. They may crawl regular websites several times a day, but that’s a different story.

Wouldn’t a log aggregation and analysis tool be the better solution rather than trying to block things that are both highly dynamic and mostly harmless? Google’s IP ranges are huge and change over time.