вторник, 28 августа 2012 г.

CentOS 5.8 + Squid 3.1 + Kerberos + Windows Server 2008 R2

Два дня убил на то, что бы настроить связку CentOS 5.8 + Squid 3.1 + Kerberos + Windows Server 2008 R2. Некоторые ошибки были досадные и отняли кучу времени. Другие, напротив, с большим трудом удалось побороть. Но в итоге всё работает :)

Имеется конфигурация:
  • Контроллер домена: Windows Server 2008 R2 Standard / ip 192.168.100.1 / dns dcbm.k43.guap.ru
  • Прокси сервер на CentOS 5.8: Squid 3.1.14 i386 / ip 192.168.100.3 / dns gateway.k43.guap.ru

Необходимо проверять доступ в интернет, используя Kerberos-аутентификацию.

Такая аутентификация имеет следующие отличительные особенности:
  1. Не требуется настройка SAMBA.
  2. Пользователям не надо вводить логин и пароль (веб-обозреватель делает это автоматически). ОС пользователей: Windows 2000 или новее, Mac OS X и Linux. Поддерживаемые веб-обозреватели: Internet Explorer 7.0 или новее (версия IE < версии 7.0 не работает с Kerberos), Mozilla Firefox версии 3.6 или новее и Safari (тесты проведены с версией 5.0.3).

Конфигурация клиентской машины

  • Пользователь должен быть членом домена и находится в базе данных контролера домена Microsoft Active Directory.
  • ОС пользователей: Windows 2000 или новее, Mac OS X и Linux. Поддерживаемые веб-обозреватели: Internet Explorer 7.0 или новее (версия IE < версии 7.0 не работает с Kerberos), Mozilla Firefox версии 3,6 или новее и Safari (тесты проведены с версией 5.0.3).
  • В настройках прокси веб-обозревателя установить полное доменное имя (FQDN) прокси-сервера (например, gateway.k43.guap.ru) и номер порта (например, 3128).

Конфигурация сервера Microsoft Active Directory

  • Необходимо добавить и настроить роль "Доменные службы Active Directory". Необходимо создать пользователя в домене, например, squid. Пароль пользователя не должен иметь срока годности ("Срок действия пароля не ограничен"). Пароль должен удовлетворять требования политик безопасности. Для оптимального уровня безопасности, пароль должен состоять из восьми символов - это минимум (буквы, цифры, а также специальные символы).
    Внимание! Пользователь должен находится в контейнере Users. Иначе будут проблемы при выполнении ktpass.



    Встречается требование выставить галочку на пункте "Без предварительной проверки подлинности Kerberos" ("Do not require Kerberos preauthentication"). Но это необязательно.
    (Если Вас смущает "Имя входа пользователя", то оно автоматически станет таким после выполнения команды ktpass, которая описана дальше).

  • Добавить группу безопасности, в которую будут входить те, кто будет получать доступ в интернет.
    Внимание! Во-избежание проблем с кодировками следует использовать английский алфавит.


  • Необходимо добавить и настроить роль "DNS-сервер". Необходимо внести прямую и обратную записи доменного имени прокси-сервера gateway.k43.guap.ru.

  • Для аутентификации прокси-сервера на контроллере домена и последующей идентификации пользователей прокси-сервером Squid, необходимо создать файл keytab. Keytab – это файл который содержит Kerberos Principal (хост, пользователь и домен) и ключи шифрования (определяются из пароля Kerberos). Это файл применяется для аутентификации в инфраструктуре Kerberos (при этом не нужно вручную вводить логин и пароль). Squid будет использовать keytab для аутентификации пользователей через протокол Kerberos.
    Создание файла keytab в командной строке контролера домена Microsoft Active Directory:
    C:\Users\Администратор.K43>ktpass -princ HTTP/gateway.k43.guap.ru@K43.GUAP.RU -mapuser squid -pass "P@ssW0rD" -ptype KRB5_NT_SRV_HST -out c:\squid.k43.guap.ru.keytab
    Targeting domain controller: DCBM.K43.GUAP.RU
    Successfully mapped HTTP/gateway.k43.guap.ru to squid.
    Password succesfully set!
    WARNING: pType and account type do not match. This might cause problems.
    Key created.
    Output keytab to c:\squid.k43.guap.ru.keytab:
    Keytab version: 0x502
    keysize 69 HTTP/gateway.k43.guap.ru@K43.GUAP.RU ptype 3 (KRB5_NT_SRV_HST) vno 3 etype 0x17 (RC4-HMAC) keylength 16 (0x0a8ef23d54e1527746c47766b18d7390)

    Если видим ошибку:
    C:\Users\Администратор.K43>ktpass -princ HTTP/gateway.k43.guap.ru@K43.GUAP.RU -mapuser squid -pass "P@ssW0rD" -ptype KRB5_NT_SRV_HST -out c:\squid.k43.guap.ru.keytab
    Targeting domain controller: DCBM.K43.GUAP.RU
    Successfully mapped HTTP/gateway.k43.guap.ru to squid.
    Password set failed! 0x00000020
    Aborted.
    
    Значит пользователь не находится в контейнере Users!

    Внимание! Очень важно соблюдать регистр при написании доменного имени. Там где написано в нижнем регистре используем нижний регистр, а там где верхний - верхний. Вроде бы элементарно, но очень многие не обращают на это внимание.
    После создания, файл "squid.k43.guap.ru.keytab" необходимо скопировать на прокси-сервер (обычно в каталог "/etc/squid").

  • Настроить сетевой доступ от прокси-сервера к контроллеру домена.

Конфигурация прокси-сервера на примере ОС CentOS 5.8

  • Прокси-серверу необходимо присвоить доменное имя gateway.k43.guap.ru. Необходимо проверить доступность DNS-сервера с помощью программы nslookup. Проверить разрешение имени прокси-сервера в IP-адрес и наоборот.
    [root@gateway ~]# nslookup
    > gateway.k43.guap.ru
    Server:         192.168.100.1
    Address:        192.168.100.1#53
    
    Name:   gateway.k43.guap.ru
    Address: 192.168.100.3
    > 192.168.100.3
    Server:         192.168.100.1
    Address:        192.168.100.1#53
    
    3.100.168.192.in-addr.arpa      name = gateway.k43.guap.ru.

  • Необходимо проверить синхронизацию времени на прокси-сервере, контролере домена и клиенте. Для правильной работы протокола Kerberos, разница во времени должна быть меньше 5 минут. Синхронизировать прокси-сервер с NTP сервером можно с помощью ntpdate.
    Внимание! Синхронизацию следует внести в планировщик, например, cron.

  • Установить Squid 3.1.
    Пакет squid-3.1 непросто найти под CentOS 5.x. Есть два репозитория на pkgs.org (на момент написания статьи), которые содержат пакет squid версии 3.1. Это CentALT с версией squid-3.1.20-1.el5.i386 и FlexBox с версией squid-3.1.14-1.el5.i386. Репозиторий CentALT содержит кривой пакет. Во-первых, при остановке squid не удаляются процессы-помощники авторизации squid_kerb_auth, squid_ldap_auth, squid_ldap_group (helper). Во-вторых, squid_kerb_auth неожиданно умирает при проверке пользователя:
    2012/08/28 18:34:45| squid_kerb_auth: DEBUG: Got 'YR YItG6gYGKwYBBqqCoI...' from squid (length: 2371).
    2012/08/28 18:34:45| squid_kerb_auth: DEBUG: Decode 'YItG6gYGKwYBBqqCoI...' (decoded length: 1774).
    2012/08/28 18:34:45| squid_kerb_auth: DEBUG: AF oYGgMIGdoAMKAQCMQw...== Администратор@K43.GUAP.RU
    2012/08/28 18:34:45| squid_kerb_auth: INFO: User Администратор@K43.GUAP.RU authenticated
    FATAL: Received Segment Violation...dying.
    2012/08/28 18:34:45| storeDirWriteCleanLogs: Starting...
    А вот пакет из FlexBox работает на ура. Поэтому ставить следует именно его. Как это сделать (или вручную установить "libecap-0.0.3-2.el5.i386.rpm" и "squid-3.1.14-1.el5.i386.rpm"). Возможно, стоит почитать тему "how to install squid 3.1 on centos 5?".

  • Установить пакеты для Kerberos аутентификации и библиотеки SASL (Simple Authentication and Security Layer):
    yum install krb5-devel krb5-libs krb5-workstation pam_krb5 cyrus-sasl-gssapi

  • Изменить конфигурации аутентификации Kerberos. В файл /etc/krb5.conf необходимо внести следующие изменения:
    [logging]
     default = FILE:/var/log/krb5libs.log
     kdc = FILE:/var/log/krb5kdc.log
     admin_server = FILE:/var/log/kadmind.log
    
    [libdefaults]
     default_realm = K43.GUAP.RU
     dns_lookup_realm = true
     dns_lookup_kdc = true
     kdc_timesync = 1
     ticket_lifetime = 24h
     forwardable = true
     proxiable = true
     default_tgs_enctypes = arcfour-rc4-md5 rc4-hmac des-cbc-crc des-cbc-md5
     default_tkt_enctypes = arcfour-rc4-md5 rc4-hmac des-cbc-crc des-cbc-md5
     permitted_enctypes = arcfour-rc4-md5 rc4-hmac des-cbc-crc des-cbc-md5
    
    [realms]
     K43.GUAP.RU = {
      kdc = dcbm.k43.guap.ru
      admin_server = dcbm.k43.guap.ru
      default_domain = k43.guap.ru
     }
    
    [domain_realm]
     .k43.guap.ru = K43.GUAP.RU
     k43.guap.ru = K43.GUAP.RU
    
    [appdefaults]
     pam = {
       debug = false
       ticket_lifetime = 36000
       renew_lifetime = 36000
       forwardable = true
       krb4_convert = false
     }
    Если у Вас несколько контроллеров домена, то параметр kdc в блоке realms повторяется несколько раз:
    [realms]
     K43.GUAP.RU = {
      kdc = dc1.k43.guap.ru
      kdc = dc2.k43.guap.ru
      kdc = dc3.k43.guap.ru
      admin_server = dcbm.k43.guap.ru
      default_domain = k43.guap.ru
     }
    Имеется большое количество мнение, о значении параметров default_tgs_enctypes, default_tkt_enctypes и permitted_enctypes. Указанные выше значения работают для Windows Server 2008 R2. По идее они должны подходить и под 2003, и под 2008. Я проверяю алгоритм с помощью команды klist -ek
    [root@gateway ~]# klist -ek /etc/squid/squid.k43.guap.ru.keytab
    Keytab name: FILE:/etc/squid/squid.k43.guap.ru.keytab
    KVNO Principal
    ---- --------------------------------------------------------------------------
       5 HTTP/gateway.k43.guap.ru@K43.GUAP.RU (ArcFour with HMAC/md5)
    
    Или попробовать следующие настройки:
    # for windows 2003
    default_tgs_enctypes = rc4-hmac des-cbc-crc des-cbc-md5
    default_tkt_enctypes =  rc4-hmac des-cbc-crc des-cbc-md5
    permitted_enctypes = rc4-hmac des-cbc-crc des-cbc-md5
    
    # for windows 2008
    default_tgs_enctypes = arcfour-rc4-md5 des-cbc-crc des-cbc-md5
    default_tkt_enctypes =  arcfour-rc4-md5 des-cbc-crc des-cbc-md5
    permitted_enctypes = arcfour-rc4-md5 des-cbc-crc des-cbc-md5

  • Изменить права доступа для keytab файла (это файла, который ранее был сформирован на домен контролере с помощью команды ktpass):
    chown squid:squid /etc/squid/squid.k43.guap.ru.keytab
    chmod 640 /etc/squid/squid.k43.guap.ru.keytab

  • Проверить правильность созданного файла keytab:
    [root@gateway ~]# kinit -V -k -t /etc/squid/squid.k43.guap.ru.keytab  HTTP/gateway.k43.guap.ru@K43.GUAP.RU
    Authenticated to Kerberos v5
    Если Вы НЕ видите "Authenticated to Kerberos v5", значит где-то дали маху. Посмотреть полученный билет Kerberos можно с помощью команды klist:
    [root@gateway squid]# klist
    Ticket cache: FILE:/tmp/krb5cc_0
    Default principal: HTTP/gateway.k43.guap.ru@K43.GUAP.RU
    
    Valid starting     Expires            Service principal
    08/29/12 07:25:12  08/29/12 17:25:06  krbtgt/K43.GUAP.RU@K43.GUAP.RU
            renew until 08/29/12 17:25:12
    
    
    Kerberos 4 ticket cache: /tmp/tkt0
    klist: You have no tickets cached

  • Для автоматической аутентификации через Squid, необходимо внести следующие изменения в исполняемый файл /etc/init.d/squid (в самом начале):
    KRB5_KTNAME=/etc/squid/squid.k43.guap.ru.keytab
    export KRB5_KTNAME
    
    KRB5RCACHETYPE=none
    export KRB5RCACHETYPE
    Внимание! Важно добавлять именно два параметра, а не только первый, как пишется во многих статьях.

  • Если необходимо использовать для работы прокси-сервера Squid не стандартный порт (например, 3180), открыть этот порт в SELinux:
    semanage port -a -t http_cache_port_t -p tcp 3180

  • Занести пароль пользователя squid (которого создавали в Active Directory) в файл "/etc/squid/squid.pass". А также сменить владельца файла и права:
    chown squid:squid /etc/squid/squid.pass
    chmod 640 /etc/squid/squid.pass

  • Проверить авторизацию пользователей в AD:
    [root@gateway ~]# /usr/lib/squid/squid_ldap_auth -R -D "squid@k43.guap.ru" -W "/etc/squid/squid.pass" -b "dc=k43,dc=guap,dc=ru" -f "sAMAccountName=%s" dcbm.k43.guap.ru
    UserNameOk PassOk
    OK
    UserNameWrong PassWrong
    ERR Success
    Первый пользователь UserNameOk имеет место быть. Второй пользователь UserNameWrong указан с ошибкой и/или неправильным паролем.

  • Проверка наличия пользователя в группе для доступа в интернет:
    [root@gateway ~]# /usr/lib/squid/squid_ldap_group -R -b "dc=k43,dc=guap,dc=ru" -f "(&(sAMAccountName=%v)(memberof=cn=%a,OU=Services,DC=k43,DC=guap,DC=ru))" -D "squid@k43.guap.ru" -W "/etc/squid/squid.pass" -S -d 192.168.100.1
    UserInGroup Internet
    Connected OK
    group filter '(&(sAMAccountName=UserInGroup)(memberof=cn=Internet,OU=Services,DC=k43,DC=guap,DC=ru))', searchbase 'dc=k43,dc=guap,dc=ru'
    OK
    UserNotInGroup Internet
    Connected OK
    group filter '(&(sAMAccountName=UserNotInGroup)(memberof=cn=Internet,OU=Services,DC=k43,DC=guap,DC=ru))', searchbase 'dc=k43,dc=guap,dc=ru'
    ERR

  • Изменяем конфигурацию squid:
    acl localnet src 192.168.100.0/24
    
    auth_param negotiate program /usr/lib/squid/squid_kerb_auth -i -s HTTP/gateway.k43.guap.ru@K43.GUAP.RU
    auth_param negotiate children 10
    auth_param negotiate keep_alive on
    
    auth_param basic program /usr/lib/squid/squid_ldap_auth -R -D "squid@k43.guap.ru" -W "/etc/squid/squid.pass" -b "dc=k43,dc=guap,dc=ru" -f "sAMAccountName=%s" 192.168.100.1
    auth_param basic children 10
    auth_param basic realm Proxy Authentication
    auth_param basic credentialsttl 2 hours
    
    acl AUTH proxy_auth REQUIRED
    external_acl_type ldap_check ttl=1200 %LOGIN /usr/lib/squid/squid_ldap_group -R -b "dc=k43,dc=guap,dc=ru" -f "(&(sAMAccountName=%v)(memberof=cn=%a,OU=Services,DC=k43,DC=guap,DC=ru))" -D "squid@k43.guap.ru" -W "/etc/squid/squid.pass" -K 192.168.100.1
    acl inet_access external ldap_check Internet
    
    http_access allow AUTH inet_access localnet
    http_access deny all
    

    А полный конфигурационный файл выглядит так:
    [root@gateway ~]# cat /etc/squid/squid.conf
    #
    # Recommended minimum configuration:
    #
    acl manager proto cache_object
    acl localhost src 127.0.0.1/32 ::1
    acl to_localhost dst 127.0.0.0/8 0.0.0.0/32 ::1
    acl localnet src 192.168.100.0/24
    
    acl SSL_ports port 443
    acl Safe_ports port 80          # http
    acl Safe_ports port 21          # ftp
    acl Safe_ports port 443         # https
    acl Safe_ports port 70          # gopher
    acl Safe_ports port 210         # wais
    acl Safe_ports port 1025-65535  # unregistered ports
    acl Safe_ports port 280         # http-mgmt
    acl Safe_ports port 488         # gss-http
    acl Safe_ports port 591         # filemaker
    acl Safe_ports port 777         # multiling http
    acl CONNECT method CONNECT
    
    #
    # Recommended minimum Access Permission configuration:
    #
    # Only allow cachemgr access from localhost
    http_access allow manager localhost
    http_access deny manager
    
    # Deny requests to certain unsafe ports
    http_access deny !Safe_ports
    
    # Deny CONNECT to other than secure SSL ports
    http_access deny CONNECT !SSL_ports
    
    # We strongly recommend the following be uncommented to protect innocent
    # web applications running on the proxy server who think the only
    # one who can access services on "localhost" is a local user
    #http_access deny to_localhost
    
    #
    # INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
    #
    
    auth_param negotiate program /usr/lib/squid/squid_kerb_auth -i -s HTTP/gateway.k43.guap.ru@K43.GUAP.RU
    auth_param negotiate children 10
    auth_param negotiate keep_alive on
    
    auth_param basic program /usr/lib/squid/squid_ldap_auth -R -D "squid@k43.guap.ru" -W "/etc/squid/squid.pass" -b "dc=k43,dc=guap,dc=ru" -f "sAMAccountName=%s" 192.168.100.1
    auth_param basic children 10
    auth_param basic realm Proxy Authentication
    auth_param basic credentialsttl 2 hours
    
    acl AUTH proxy_auth REQUIRED
    external_acl_type ldap_check ttl=1200 %LOGIN /usr/lib/squid/squid_ldap_group -R -b "dc=k43,dc=guap,dc=ru" -f "(&(sAMAccountName=%v)(memberof=cn=%a,OU=Services,DC=k43,DC=guap,DC=ru))" -D "squid@k43.guap.ru" -W "/etc/squid/squid.pass" -K 192.168.100.1
    acl inet_access external ldap_check Internet
    
    http_access allow AUTH inet_access localnet
    
    # And finally deny all other access to this proxy
    http_access deny all
    
    # Squid normally listens to port 3128
    http_port 3128
    
    # We recommend you to use at least the following line.
    hierarchy_stoplist cgi-bin ?
    
    # Uncomment and adjust the following to add a disk cache directory.
    #cache_dir ufs /var/spool/squid 100 16 256
    
    # Leave coredumps in the first cache dir
    coredump_dir /var/spool/squid
    
    # Add any of your own refresh_pattern entries above these.
    refresh_pattern ^ftp:           1440    20%     10080
    refresh_pattern ^gopher:        1440    0%      1440
    refresh_pattern -i (/cgi-bin/|\?) 0     0%      0
    refresh_pattern .               0       20%     4320

  • Далее запустить squid.
    service squid start

    В случае ошибок в основном смотрим в
    tail -f /var/log/squid/cache.log

Важно понимать, как происходит авторизация в squid машин в домене и не в домене. Во-первых, сперва производится negotiate-аутентификация, а затем basic-аутентификация. Машины в домене проходят именно negotiate-аутентификацию, а машины не в домене могут пройти только basic-аутентификацию. Поэтому на машинах не в домене можно при запросе пароля в первый раз ввести что угодно (они не пройдут аутентификацию, поскольку не входят в домен), а во второй раз - правильные данные (чтобы пройти  basic-аутентификацию). Я проверял и на ноутбуке и на iPhone.

Надеюсь ничего не упустил. Это минимальная конфигурация. Чтобы не засорять логи отладочной информацией можно выключить параметр -d в /squid_kerb_auth и даже параметр -i (если они у вас остались).

Далее можно сделать ротацию журнальных файлов. И разделить пользователей на группы с различными ограничениями по сайтам и пропускной способности канала (пример).

При подготовке материала в основном использовались:
http://xgu.ru/wiki/Squid,_Kerberos_и_LDAP
http://lanzelotti.blogspot.com/2011/11/autenticando-squid-no-ad-20032008-via.html
Но было перерыто куча сайтов, документации, потрачено много нервов и выпито много чаю.

4 комментария:

  1. блин, вроде все сделал и ошибок не было...
    но почему-то в инет могут выходить все пользователи(не важно в группе internet они или нет, даже если локально залогинился все равно есть доступ)
    в чем косяк может быть?

    ОтветитьУдалить
    Ответы
    1. Я думаю, что у вас настроена маршрутизация и не выставлено ограничено на брандмауэре (iptables - стандартный брандмауэр для CentOS 5.x, поэтому далее речь о нём).

      1. Настроил бы iptables:
      а) Включил бы запись в логи в iptables. Посмотрел блокируется ли трафик на 80 порт.
      -A FORWARD -j LOG --log-level DEBUG --log-prefix "FW FORWARD DROP:"
      Если блокировки нет (и соответственно нет сообщений), то пункт 2.

      б) трафик в цепочке FORWARD по 80 порту блокировался (желательно применять политику DROP и не делать явного разрешения передачи по 80 порту)
      :FORWARD DROP [0:0]

      в) в цепочку PREROUTING добавляю перенаправление данных по 80 порту на SQUID (переброс с 80 порта на SQUID, чтобы пользователи могли видеть сообщение об ошибке в виде соответствующей страницы SQUID):
      -A PREROUTING -p tcp -s 192.168.100.0/24 --dport 80 -j REDIRECT --to-ports 3128

      г) в цепочке INPUT выставить разрешение на входящие соединения для прокси сервера из локальной сети:
      -A INPUT -p tcp -s 192.168.100.0/24 --dport 3128 -j ACCEPT

      После этого пользователи, у кого явно не прописан прокси сервер не смогут смотреть страницы.

      2. Посмотрел бы журналы SQUID на входящие соединения:
      tail -f /var/log/squid/access.log
      Если видны соединения, то поздравляю!
      Если в них пусто, значит соединения осуществляются мимо прокси сервера (возвращаемся к проблеме маршрутизации - пункт 1), либо у пользователя не прописан прокси сервер (но при правильной настройке брандмауэра он не видит страничек).

      Удалить
  2. привет ! вы не могли бы оказать немного помощь по данному вопросу - второй день не могу завести керберос ! Буду очень признателен maodzedun_at_gmail.com

    ОтветитьУдалить