FreeRadius Notes: различия между версиями

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
Строка 423: Строка 423:
 
==<code>User-Password</code>==
 
==<code>User-Password</code>==
   
<code>User-Password</code> is strictly a request pair. It should not be present in any of the other lists.
+
<code>User-Password</code> это тарибут который должен содержаться только в запросе и более нигде
 
<BR>
 
<BR>
<code>User-Password</code> is included in the request from the NAS. It contains the plaintext version of the password the user provided to the NAS.
+
<code>User-Password</code> этот атрибут который пользователь передал на NAS в том видже в котором он был передан <BR>
  +
In order to authenticate a user, a module needs to compare the contents of User-Password with a control pair like <code>Cleartext-Password</code>.
 
  +
Что бы <code>authenticate</code> подльзователя модуль сравнивает значение атрибута <code>User-Password</code> со значением (например) <code>Cleartext-Password</code> из списка атрибутов <code>control</code>.
 
<BR>
 
<BR>
 
In a users file entry when setting reference passwords you'll see entries like:
 
In a users file entry when setting reference passwords you'll see entries like:

Версия 15:24, 20 марта 2024

Это просто сборник ссылок и заметок

Минимальный рабочий конфиг

Тут чертовски важен порядок модулей - если переставить местами pap/files то получится что pap не сможет получить пароль

sites-enabled/default

server default {
    listen {
        type = auth
        ipv4addr = *
        port = 1812
        limit {
            max_connections = 16
            lifetime = 0
            idle_timeout = 30
        }
    }

    listen {
        ipv4addr = *
        port = 1813
        type = acct
    }


    instantiate {
        exec
        expr
        expiration
    }

    authorize {
        files
        pap
    }

    authenticate {
        Auth-Type PAP {
            pap
        }
    }
} # end of SERVER

Клиенты clients.conf

client localhost {
    ipaddr = 127.0.0.1
    proto = *
    secret = secret
    require_message_authenticator = no
    limit {
        max_connections = 16
        lifetime = 0
        idle_timeout = 30
    }
}

Модуль PAP mods-enabled/pap

pap {
#       normalise = yes
        auto_header = no
}

Модуль files

mods-enabled/files

files {
    moddir = ${modconfdir}/${.:instance}
    #key = "%{%{Stripped-User-Name}:-%{User-Name}}"
    filename  = ${moddir}/authorize
    usersfile = ${moddir}/authorize
#    acctusersfile = ${moddir}/accounting
}

mods-config/files/authorize

bob     Cleartext-Password := "hello"
        Reply-Message := "Hello, %{User-Name}"

Проверка работы минимальной конфигурации


  • Для проверки использую команду radtest bob hello localhost 0 secret
    • bob - имя пользователя, атрибут User-Name
    • hello - пароль, который будет передан в атрибуте User-Password
    • localhost - адрес куда отправить запрос
    • 0 - номер (виртуального) порта, NAS-Port
    • secret - radius shared secret, который указан в настройках сервера и клиента

По сути тут логика такая

  • "Пришел" пользователь User-Name = "bob" User-Password = "hello"
  • Его проверили по файлу (модуль files ищет пользователя в файле, имя файла определено конфигурацией модуля) и находит, о чем говорит запись files: users: Matched entry bob at line 4
  • Далее для модулей вызываных ниже по конфигу будут доступны атрибуты которые добавил модуль files а именно:
bob     Cleartext-Password := "hello"
        Reply-Message := "Hello, %{User-Name}"
  • При этом модуль files по сути не делает проверок - он только сопоставляет запрос, и по ключу который определен в конфигурации (key = "%{%{Stripped-User-Name}:-%{User-Name}}") находит (или не находит) атрибуты.


Запись в логах вида:

[files] = ok

Означает что такой пользователь существует, НО не означает что он успешно авторизован.

  • Далее модуль PAP осуществляет проверку пароля. Важно то, что пароль в описании пользователя должен содержаться в атрибутах "known good", в нашем случае - Cleartext-Password



  • Собственно на этом все.
Fri Jul 14 18:07:17 2023 : Debug: (0) Received Access-Request Id 51 from 127.0.0.1:54599 to 127.0.0.1:1812 length 73
Fri Jul 14 18:07:17 2023 : Debug: (0)   User-Name = "bob"
Fri Jul 14 18:07:17 2023 : Debug: (0)   User-Password = "hello"
Fri Jul 14 18:07:17 2023 : Debug: (0)   NAS-IP-Address = 10.90.1.213
Fri Jul 14 18:07:17 2023 : Debug: (0)   NAS-Port = 0
Fri Jul 14 18:07:17 2023 : Debug: (0)   Message-Authenticator = 0xa051e8612e62faaa98baa723ceb98219
Fri Jul 14 18:07:17 2023 : Debug: (0) session-state: No State attribute
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing section authorize from file /etc/freeradius/3.0/sites-enabled/default
Fri Jul 14 18:07:17 2023 : Debug: (0)   authorize {
Fri Jul 14 18:07:17 2023 : Debug: (0)     modsingle[authorize]: calling files (rlm_files)
Fri Jul 14 18:07:17 2023 : Debug: (0) files: users: Matched entry bob at line 4
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: FROM 1 TO 0 MAX 1
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: Examining Reply-Message
Fri Jul 14 18:07:17 2023 : Debug: Hello, %{User-Name}
Fri Jul 14 18:07:17 2023 : Debug: Parsed xlat tree:
Fri Jul 14 18:07:17 2023 : Debug: literal --> Hello,
Fri Jul 14 18:07:17 2023 : Debug: attribute --> User-Name
Fri Jul 14 18:07:17 2023 : Debug: (0) files: EXPAND Hello, %{User-Name}
Fri Jul 14 18:07:17 2023 : Debug: (0) files:    --> Hello, bob
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: APPENDING Reply-Message FROM 0 TO 0
Fri Jul 14 18:07:17 2023 : Debug: (0) files: ::: TO in 0 out 0
Fri Jul 14 18:07:17 2023 : Debug: (0)     modsingle[authorize]: returned from files (rlm_files)
Fri Jul 14 18:07:17 2023 : Debug: (0)     [files] = ok
Fri Jul 14 18:07:17 2023 : Debug: (0)     modsingle[authorize]: calling pap (rlm_pap)
Fri Jul 14 18:07:17 2023 : Debug: (0)     modsingle[authorize]: returned from pap (rlm_pap)
Fri Jul 14 18:07:17 2023 : Debug: (0)     [pap] = updated
Fri Jul 14 18:07:17 2023 : Debug: (0)   } # authorize = updated
Fri Jul 14 18:07:17 2023 : Debug: (0) Found Auth-Type = PAP
Fri Jul 14 18:07:17 2023 : Debug: (0) # Executing group from file /etc/freeradius/3.0/sites-enabled/default
Fri Jul 14 18:07:17 2023 : Debug: (0)   Auth-Type PAP {
Fri Jul 14 18:07:17 2023 : Debug: (0)     modsingle[authenticate]: calling pap (rlm_pap)
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Login attempt with password "hello" (5)
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: Comparing with "known good" Cleartext-Password "hello" (5)
Fri Jul 14 18:07:17 2023 : Debug: (0) pap: User authenticated successfully
Fri Jul 14 18:07:17 2023 : Debug: (0)     modsingle[authenticate]: returned from pap (rlm_pap)
Fri Jul 14 18:07:17 2023 : Debug: (0)     [pap] = ok
Fri Jul 14 18:07:17 2023 : Debug: (0)   } # Auth-Type PAP = ok
Fri Jul 14 18:07:17 2023 : ERROR: (0) Cannot proxy packets unless 'proxy_requests = yes'
Fri Jul 14 18:07:17 2023 : Debug: (0) Empty post-auth section in virtual server "default".  Using default return values.
Fri Jul 14 18:07:17 2023 : Auth: (0) Login OK: [bob/hello] (from client localhost port 0)
Fri Jul 14 18:07:17 2023 : Debug: (0) Sent Access-Accept Id 51 from 127.0.0.1:1812 to 127.0.0.1:54599 length 32
Fri Jul 14 18:07:17 2023 : Debug: (0)   Reply-Message = "Hello, bob"
Fri Jul 14 18:07:17 2023 : Debug: (0) Finished request
Fri Jul 14 18:07:17 2023 : Debug: Waking up in 4.9 seconds.


Ошибочная конфигурация

Если переставить модули местами и вместо

    authorize {
        files
        pap
    }

Написать модули в обратном порядке

    authorize {
        pap
        files
    }

То на момент проверки пароля модулем PAP, атрибут Cleartext-Password еще не будет доступен о чем и будет сказано в логах:

Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: No "known good" password found for the user.  Not setting Auth-Type
Sat Jul 15 12:49:59 2023 : WARNING: (0) pap: Authentication will fail unless a "known good" password is available
...

Sat Jul 15 12:49:59 2023 : WARNING: (0) No module configured to handle comparisons with &control:Cleartext-Password
Sat Jul 15 12:49:59 2023 : WARNING: (0) Add pap or chap to the authorize { ... } and authenticate { ... } sections of this virtual server to handle this "known good" password type
Sat Jul 15 12:49:59 2023 : ERROR: (0) No Auth-Type found: rejecting the user via Post-Auth-Type = Reject

Не смотря на то что модуль files говорит что "все хорошо" авторизация не работает.

Sat Jul 15 12:49:59 2023 : Debug: (0)     [files] = ok 


How the users file works

Существуют три списка атрибутов (точнее пар атрибут - значение )
Они привязаны к конкретному запросу/ответу к серверу, и не доступны из других запросов/ответов

  • request - содержит список атрибут-значение которые получены в запросе от NAS
  • control - изначально это пустой список, который определяет как и какие модули будут обрабатывать запрос. Этот список заполняется содулями (например files или python) или с помощью ulang
  • reply - содержит список атрибутов которые будут отправлены назад на NAS

Модуль users file определяет какие пары проверять а какие пары добавлять в зависимости их расположения в конфигурационном файле а так же в зависимости от операторов.
Пример:

bob    Cleartext-Password := "hello"
       Reply-Message := "Hello, %{User-Name}"

Первая строка содержит пары атрибут-значение для проверки и пары которые будут добавлены в список control,
добавление в список control происходит при полном совпадении всех проверок.
Пары (в первой строке!) которые проверяются которые добавляются в список control можно отличить по используемым операторам

  • Если используются операторы присвоения := or = то пара атрибут-значение обрабатывается как control (добавляется в список)
  • Если используются операторы сравнения >, <, ==, >=, <=, =~ то пара атрибут-значение используются для проверки соответвия

В примере выше используется только одна пара Cleartext-Password := "hello" где используется присвоение, те для этого пользователя будет только добавлена пара в список control (а проверка будет выполнена на другой стадии и другим модулем)
Все пары кроме первой строки содержат только пары которые будут добавлены в ответ.

Описание операторов

Файлы
Operator Пример Использование в check
(users и тому подобное), или в условиях unlang
Использование в reply
(users и тому подобное), или в блоках unlang update
=

Attribute = Value

  • Используется для установки атрибутов конфигурации сервера
  • Не допускается для операторов проверки атрибутов (например проверки пароля)
  • Используется для добавления пары атрибут-значение, только если такой атрибут не был добавлен раньше (если был то значение изменено не будет)
 :=
 
lameuser       Auth-Type := Reject
               Reply-Message = "Your account has been disabled."
steve  Cleartext-Password := "testing"
       Service-Type = Framed-User

Всегда совпадает при проверках, и добавляет в control атрибут-значение, если такой атрибут уже был, то замещает значение. (по сути оператор присвоения) В первом примере пользователь всегда получит
Auth-Type := Reject , если ниже нет другого условия (например для группы), которое переопределит Auth-Type
Второй пример показывает как правильно установить пользователю пароль. Эта конструкция может показаться странной, так как присвоение пароля := а не сравнение.
Тут важно понимать следующее

  • Эта запись будет работать если в запросе есть атрибут User-Name со значением "steve"
  • В control словарь будет помещен атрибут Cleartext-Password со значением "testing"
  • В reply словарь будет помещен атрибут Service-Type со значением "Framed-User"
  • При этом проверка пароля будет происходить в зависимости от того что опеределено в настройке сервера
server {

    authorize {
            files
            pap
    }
    authenticate {
        Auth-Type PAP {
                pap
        }
    }
  • В примере в секции authorize выше модуль files добавит атрибут Cleartext-Password, модуль pap добавит атрибут Auth-Type со значением "PAP"
  • И только в секции authenticate будет происходить проверка пароля

Для атрибутов в ответе (reply) работает так же, как оператор присвоения (добавляет атрибут-значение если его не было, переопределяет значение если атрибут уже был)

automate        Cleartext-Password := "pppassss"
                User-Service-Type := 6
==
swilson        Service-Type == Framed-User, Huntgroup-Name == "alphen"
               Framed-IP-Address = 192.0.2.65,
               Fall-Through = Yes

Операция сравнения для check атрибутов, успешна если совпадает атрибут присутствует и его значение совпадает с указанным.
В примере при совпадении User-Name со значением "swilson" и если в запросе присутвуют атрибут Service-Type со значением "Framed-User" и Huntgroup-Name со значением "alphen"
Сам атрибут Huntgroup-Name должен быть установлен дополнительно в модуле preprocess

    authorize {
        preprocess
        ...
    }

Не применимо

+= Attribute += Value
Cisco-Account-Info += "APOLICY_MAP_SERVICE_ON_SESSION_START_",
Cisco-Account-Info += "NPOLICY_MAP_SERVICE_ON_SESSION_START_"
При проверке атрибутов - всегда дает совпадение и добавляет атрибут-значение к словарю конфигурационных атрибутов При формировании ответа добавляет атрибуты к ответу (не переписывая существующие)
 != Текст ячейки Дает совпадение, если атрибут присутствует в запросе и его значение не равно указанному (соответственно если атрибута нет то совпадение невозможно) Не применимо
> Текст ячейки Дает совпадение, если атрибут присутствует в запросе и его значение больше указанного Не применимо
>= Текст ячейки Дает совпадение, если атрибут присутствует в запросе и его значение больше или равно указанному Не применимо

<

Текст ячейки Дает совпадение, если атрибут присутствует в запросе и его значение меньше указанного Не применимо
<= Текст ячейки Дает совпадение, если атрибут присутствует в запросе и его значение меньше или равно указанному Не применимо
=~ Текст ячейки Дает совпадение, если атрибут присутствует в запросе и его значение совпадает с регулярным выражением, применим только для строк Не применимо
 !~ Текст ячейки Дает совпадение, если атрибут присутствует в запросе и его значение НЕ совпадает с регулярным выражением, применим только для строк Не применимо
=* Текст ячейки Дает совпадение, если атрибут присутствует в запросе и его (значение не проверяется) Не применимо
 !* Текст ячейки Дает совпадение, если атрибут НЕ присутствует в запросе и его (значение не проверяется по причине отсутвия) Не применимо



Cleartext-Password

Cleartext-Password это исключительно control пара атрибут-гачение и эта пара не должна присутвовать ни в каком другом списке
Cleartext-Password это один из списка атрибутов известных как 'known good' password
который содержит пользовательский пароль в открытом виде.
Другой пример из этого набора "хорошо известных" SSHA-Password - который содержит salted SHA hash от пользовательского пароля.
Проверка пользовательского пароля происходит cопоставлением атрибута из списка the 'known good' password атрибутов
которые содержаться в списке control модулями которые могут authenticate пользователя - это может быть модуль rlm_pap
или другой - например самописный на python

    authenticate {
        Auth-Type ISG {
            python3_isg
        }
    }

По сути, модуль rlm_pap сравнивает значение User-Password которое вставил другой модуль - files как в этом примере или sql или еще какой-то

User-Password

User-Password это тарибут который должен содержаться только в запросе и более нигде
User-Password этот атрибут который пользователь передал на NAS в том видже в котором он был передан

Что бы authenticate подльзователя модуль сравнивает значение атрибута User-Password со значением (например) Cleartext-Password из списка атрибутов control.
In a users file entry when setting reference passwords you'll see entries like:

my_username Cleartext-Password := "known_good_password"

That is, if the username matches the value on the left (my_username), then insert the control pair Cleartext-Password with the value "known_good_password".
To answer the first question the reason why:

shad Cleartext-Password == "test"


Does not work, it is because you are telling the files module to search in the request list, for a pair which does not exist in the request list, and should never exist in the request list.
You might now be thinking oh, i'll use User-Password == "test" instead, and it'll work. Unfortunately it won't. If the password matches then the entry will match, but the user will still be rejected, see below for why.

Auth-Type

Auth-Type is strictly a control pair. It should not be present in any of the other lists.

There are three main sections in the server for dealing with requests 'authorize', 'authenticate', 'post-auth'.

authorize

authorize is the information gathering section. This is where database lookups are done to authorise the user, and to retrieve reference passwords. It's also where Auth-Type is determined, that is, the type of authentication we want to perform for the user.

authenticate

Authenticate is where a specific module is called to perform authentication. The module is determined by Auth-Type.


Post-Auth is mainly for logging, and applying further policies, the modules run in Post-Auth are determined by the response returned from the module run in Authenticate.

The modules in authorize examine the request, and if they think they can authenticate the user, and Auth-Type is not set, they set it to themselves. For example the rlm_pap module will set Auth-Type = 'pap' if it finds the User-Password in the request.

If no Auth-Type is set the request will be rejected.

So to answer your second question, you're forcing pap authentication, which is wrong, you should let rlm_pap set the Auth-Type by listing pap after the files module in the authorize section.

When rlm_pap runs in authenticate, it looks for a member of the set of 'reference' passwords described above, and if it can't find one, it rejects the request, this is what's happening above.

There's also a 'magic' Auth-Type, Accept, which skips the authenticate section completely and just accepts the user. If you want the used to do cleartext password comparison without rlm_pap, you can use:

shad Auth-Type := Accept, User-Password == "test"