Socks-сервер Dante или как одна буква может «съесть» пару суток времени

    Каждый раз сталкиваясь с таким «рабочим моментом» я задумываюсь надо ли его решение давать миру или оно мелочно для других, но на этот раз решил-таки выложить. Эта статья больше из разряда заметки на манжетах и написана лишь из-за скудности информации о настройке Dante в нете и хроманием на обе ноги официальной документации.
    В пятницу утром заказчик обратился с просьбой поднять socks-сервер на ~100 пользователей, с авторизацией по логину/паролю, привязкой IP и отправкой запросов с того же IP к которому конектится пользователь. При этом заказчик поинтересовался сроком выполнения работ и, хоть я не люблю делать прогнозы по времени установки/настройки, заверил его, что часа через 3-4 альфа-версия будет готова. Ну правда — погуглив выбрать подходящий socks-сервер, установить, почитать маны, подправить под себя дефолтный конфиг… в 4 часа должен вложиться.
    ОС FreeBSD 9.2, но всё нижеописанное справедливо и для 10-ки.

    Как ни странно, подходящих под запросы заказчика socks-серверов нашлось всего два: 3proxy 0.6.1 и Dante (в портах 1.3.2). Может я, конечно, что-то упустил, но либо нет авторизации, либо нет режима int_ip -> ext_ip. Возможно этим запросам соответствует squid, но ставить этого монстра ради простой задачи не хотелось.
    Я ничего не имею против 3proxy, сам с ним работаю не первый год в режиме портмэппинга, нареканий особых нет, но разработка его стоит с 2009 года, код грязноват и слышал неоднократные отзывы о его прожорливости под большой нагрузкой.
    Итак, Dante.
    До версии 1.3 поддержки int_ip -> ext_ip Dante не имел, точнее имеется схожая реализация в платной версии по весьма недедемократичной цене в EUR400, однако, Lysenko Konstantin добавил данный функционал в виде патча «same-same» в Dante 1.2.2 и он был включён в релиз 1.3.0.
    Не берусь утверждать работала ли данная конструкция в 1.3.0, но в 1.3.2 запросы упорно уходят с первого найдённого в конфиге external-ip. Перелопатив скудный ман я обратился к странице разработчика. Информации там несколько больше, но запустить same-same так как мне требовалось не удалось. Однако, с ноября 2013 года на сайте есть версия 1.4, которая почему-то не включена в порты. Качаем, собираем.
    Надо отметить, что конфиг в 1.4 претерпел косметические изменения, хотя в манах по прежнему приводятся примеры с параметрами прежних версий, на которые Dante ругается как deprecated и, иногда, подсказывает верные новые параметры.

    Тестовый конфиг:
    /usr/local/etc/sockd.conf
    # cat /usr/local/etc/sockd.conf
    logoutput: /var/log/socks/socks.log
    
    debug: 0
    
    internal: 11.12.13.1          port = 1080
    internal: 11.12.13.2          port = 1080
    internal: 11.12.13.3          port = 1080
    external: 11.12.13.1
    external: 11.12.13.2
    external: 11.12.13.3
    
    external.rotation: same-same
    
    socksmethod: username
    
    user.privileged: root
    user.unprivileged: nobody
    user.libwrap: nobody
    
    compatibility: sameport
    
    client pass {
            from: 0.0.0.0/0 port 1-65535 to: 0.0.0.0/0
    }
    
    client block {
            from: 0.0.0.0/0 to: 127.0.0.0/8
            log: connect error
    }
    
    client block {
            from: 0.0.0.0/0 to: 0.0.0.0/0
            log: connect error
    }
    
    
    socks pass {
            from: 21.22.23.0/24 to: 0.0.0.0/0
            log: connect error
            user: chaturanga
    }
    
    socks block {
            from: 0.0.0.0/0 to: 0.0.0.0/0
            log: connect error
    }
    
    


    И… вопреки ожиданиям в 1.4 same-same также не заработал. На этот раз в отличии от 1.3 посыпались ошибки типа

    warning: getoutaddr(): using external.rotation = same-same, local address 21.22.23.48 was selected for forwarding from our local client 21.22.23.48.45980 to target 77.72.80.15.80, but that local address is not set on our external interface(s).  Configuration error in /usr/local/etc/sockd.conf?
    
    

    , где 21.22.23.48 — адрес моей локальной машины в то время как здесь должен быть internal-IP сервера к которому которому подключается клиент. Смутившись фразой «Configuration error in /usr/local/etc/sockd.conf?» курочу конфиг и штудирую маны, но, так как информации в них мало, лезу в лучший ман — исходники. Улыбаясь комментариям в виде
       /*
        * Just return the first address of the appropriate type from our internal
        * list and hope the best.
        */
    

    нахожу-таки источник проблем (./sockd/sockd_request.c, line 4173):
    /*
    * Find address to bind for client. First the ipaddress.
    */
    if (getoutaddr(&io->dst.laddr,
    &io->src.raddr,
    req.command,
    target,
    emsg,
    emsglen) == NULL)
    return -1;

    Меняю &io->src.raddr на &io->src.laddr, пересобираю, запускаю и, наконец, вижу желанное:
    info: pass(1): tcp/connect [: username%chaturanga@21.22.23.48.46050 11.12.13.3.1080 -> 11.12.13.3.27819 77.72.80.15.80
    

    Тихо матерясь, оформляю баг-репорт разработчикам.
    В итоге вместо заявленных 3-4 часов в чтении, додумывании конфигов, попытке запустить Dante не в jail'e, тестах на Centos вместо FreeBSD и копании в исходниках убил пару дней… Вот и обещай после этого…

    UPD1: Пока писалась заметка ответил разработчик:
    Hello, thank you for the bug-report. You are correct, there is an
    error here. Your proposed solution is basically correct, though
    we will probably implement the fix slightly differently.


    UPD2: И в ходе дальнейшей переписки:
    Depending on the current workload, I doubt I will be able to provide
    you with our official patch for at least another month.

    Ну и на том спасибо.

    UPD3(2014-09-03):
    Разработчик сообщил, что баг исправлен (v.1.4.1).
    Проверил, всё работает как положено.
    • +23
    • 30.9k
    • 8
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 8

      +1
      ssh в качестве socks-сервера уже не катит? Уж с авторизацией у него просто зашибись.
        0
        ЕМНИП, то SSH не умеет авторизацию когда работает в качестве socks-proxy. Или уже умеет?
          0
          ssh умеет разрешать или запрещать socks-прокси для конкретного пользователя. После этого он работает как socks-прокси для тех, кому разрешили. Или я не так понял задачу?
            0
            К SSH еще подключиться надо, а порт прокси можно просто ограничить локальными подключениями (не уверен насчет возможностей самого SSH-клиента, но есть же файерволы etc).
            0
            dante намного гибче в этом плане — правила всякие и т.п.
            +1
            Разработчик сообщил, что баг исправлен (v.1.4.1).
            Проверил, всё работает как положено.
              0
              Спасибо, информация из поста очень пригодилась. В убунту почему-то до сих пор версия 1.1.19.
              0
              Спасибо за информацию. Но вот странно, обновился я на Centos до 1.4.1

               /usr/local/sbin/sockd -v
              Dante v1.4.1.  Copyright (c) 1997 - 2014 Inferno Nettverk A/S, Norway
              
              


              И не заработала rotation.
              В логах ошибка как при баге

              Apr 17 10:12:25 (1429279945.268557) sockd[20825]: info: block(1): tcp/connect ]: 77.52.95.211.6347 31.184.193.76.1090 -> 0.0.0.0.0 206.190.36.45.80: could not bind address to use on external side: using external.rotation = same-same, local address 31.184.193.76 was selected for forwarding from our local client 77.52.95.211.6347 to target 206.190.36.45.80, but that local address is not set on our external interface(s). Configuration error in /etc/sockd.conf?

              Only users with full accounts can post comments. Log in, please.