Можно как-то добавить такую штуку простым способом?

Привет всем, вопрос к разработчикам наверное
Каким простым способом можно сделать такую штуку

  1. метим пакеты в iptables, типа такого iptables -t mangle -A PREROUTING -m set --match-set marked_ips src -j MARK --set-mark 1
  2. в логах/контексте http или server получаем зарезервированную переменну с этим значение
  3. можно использовать в map/if и логах

Добрый день.

Какого-либо простого способа не видится. Демон работает в пространстве пользователя и вообще ничего не знает об отдельных пакетах, а читает уже декапсулированные данные из сокетного буфера. Более того, уже на программном уровне модуль HTTP оперирует L7-концепциями, отдельными HTTP запросами.

В man 7 socket упоминается опция SO_MARK, но я подозреваю, что getsockopt(SO_MARK) на соединении просто вернет ранее установленное через setsockopt(SO_MARK) значение. Возможно, что я ошибаюсь.

Что-то типа getsockopt(fd, SOL_SOCKET, SO_MARK, &mark, &len);
По примерам это похоже на точто нужно
Получается нужно “поднять” эту маркировку до контекст соединения angie по аналогии с remote_addr/remote_port/server_port

Я полагаю, что все же getsockopt(fd, SOL_SOCKET, SO_MARK, &mark, &len); не вернет то, что было прислано. Оно лишь вернет то значение, что могло быть ранее установлено через setsockopt() для этого дескриптора (т.е. никакого) и потому смысла не имеет.

Я рекомендую всё же проверить на простом тестовом примере, прежде чем пытаться что-то делать дальше.

Возможно вот релевантный модуль GitHub - m4ttr/skmark: netfilter skmark - который мог бы устанавливать то, что затем можно прочитать через getsockopt().

Сделал побыстрому исправления и собрал.

  1. Да - не получаю что было в iptables, оно не попадает на сокет,
  2. нужны права CAP_NET_ADMIN
  3. похоже, что тут нужен TPROXY, чтобы это реализовать
  4. для TPROXY нужен еще и IP_TRANSPARENT и больше доработок

Из быстрых и готовых решений, видимо - взять HAProxy в режиме transparent и передать маркировку через свой заголовок в angie

Не очень понимаю, а как HAProxy в режиме transparent тут поможет?
У Angie есть аналогичный режим: Proxy — Angie Software

Короче, парни, был не прав, вот рабочий вариант
в системе от root делаем
sysctl -w net.ipv4.tcp_fwmark_accept=1
iptables -t mangle -A PREROUTING -s 192.168.0.0/24 -p tcp --dport 80 -j MARK --set-mark 100
iptables -t mangle -A PREROUTING -s 192.168.1.0/24 -p tcp --dport 80 -j MARK --set-mark 101
лучше для списков потом использовать ipset

В angie.service , обычно тут лежит /etc/systemd/system/multi-user.target.wants/angie.service
[Service]
AmbientCapabilities=CAP_NET_ADMIN

Конфиг - angie.conf:

load_module modules/ndk_http_module.so;
load_module modules/ngx_http_lua_module.so;
load_module modules/ngx_stream_lua_module.so;
load_module modules/ngx_http_set_misc_module.so;

Конфиг - http.d/default.conf

log_format combined_mark '$remote_addr - $remote_user [$time_local] '
                             '"$request" $status $body_bytes_sent '
                             '"$http_referer" "$http_user_agent" '
                             'fw_mark=$fw_mark';

    lua_shared_dict locks 1m;
    init_by_lua_block {
        local ffi = require("ffi")
        ffi.cdef[[
            typedef int ngx_socket_t;
            struct ngx_connection_s {
                void               *data;
                void               *read;
                void               *write;
                ngx_socket_t        fd;
            };
            struct ngx_http_request_s {
                uint32_t                  signature;
                struct ngx_connection_s  *connection;
            };
            int getsockopt(int sockfd, int level, int optname, void *optval, int *optlen);
        ]]
    }
server {
    listen       0.0.0.0:80;
    server_name  localhost _;
    access_log /var/log/angie/access_marked.log combined_mark;
    location / {
            set_by_lua_block $fw_mark {
                local ok, base = pcall(require, "resty.core.base")
                if not ok then
                    ngx.log(ngx.ERR, "ERROR: resty.core.base not found! Install lua-resty-core")
                    return 0
                end
                local ffi = require("ffi")
                local r_ptr = base.get_request()
                if not r_ptr then
                    ngx.log(ngx.ERR, "DEBUG: Cannot get request pointer")
                    return 0
                end
                local r = ffi.cast("struct ngx_http_request_s *", r_ptr)
                if r.connection == nil then
                    ngx.log(ngx.ERR, "DEBUG: No connection in request?")
                    return 0
                end
                local fd = r.connection.fd
                ngx.log(ngx.ERR, "DEBUG: Found FD via struct: ", fd)
                local SOL_SOCKET = 1
                local SO_MARK = 36
                local val = ffi.new("int[1]")
                local len = ffi.new("int[1]", ffi.sizeof("int"))
                if ffi.C.getsockopt(fd, SOL_SOCKET, SO_MARK, val, len) == 0 then
                    ngx.log(ngx.ERR, "DEBUG: Getsockopt SUCCESS! Mark: ", val[0])
                    return tostring(val[0])
                else
                    ngx.log(ngx.ERR, "DEBUG: Getsockopt failed")
                    return 0
                end
            }
            #proxy_set_header X-Packet-Mark $fw_mark;
            #proxy_pass http://127.0.0.1:8080;
            return 200 "FW Mark: $fw_mark\n";
}}