최근 OpenVPN-AS의 가격이 크게 오르면서 대체 소프트웨어인 SoftEther를 사용하기 위해 SoftEther의 LDAP 인증을 알아봤으나, SoftEther는 LDAP 인증을 지원하지 않았다. 대신 RADIUS와 Active Directory를 지원하는데, RADIUS에 LDAP을 Backend로 붙일 수 있어서 이것을 구현하는 과정에서 여러가지 삽질을 했던 터라 기록을 남기기 위해 포스팅 한다.

업무환경: RADIUS와 LDAP은 서로 다른 서버에서 운영되며, LDAP은 패스워드를 saslauthd를 통해 상위 기관으로 넘겨서 인증을 확인한다.

RADIUS 서버: Ubuntu 18.04
LDAP 서버: Ubuntu 18.04, LDAP/LDAPS + SASLauthd

패키지 설치 (freeradius-ldap 하나면 필요한 패키지는 알아서 딸려온다)

apt install freeradius-ldap

우선 FreeRADIUS의 LDAP 모듈을 활성화한다. Apache의 a2enmod 같은 명령어가 없기 때문에 수동으로 링크를 걸어줘야한다.

cd /etc/freeradius/3.0/mods-available
ln -s ldap ../mods-enabled/

LDAP 모듈부터 설정한다. LDAP 서버는 이미 잘 설정되어 운영되고 있는 것을 전제로 하며, 아래에 적힌 설정 외 다른 설정은 디폴트를 그대로 둔다.

ldap {
    server = 'ldap.company.com'
    port = 636
    identity = 'cn=registeruser,dc=company,dc=com'
    password = 'Password'
    base_dn = 'ou=people,dc=company,dc=com'
    sasl {}
    user {
        sasl  {}
    }
    tls {
        ca_file = "/etc/ssl/certs/yourcompany_ca_chain.pem"
        certificate_file = "/etc/ssl/certs/yourcompany_cert.crt"
        private_key_file = "/etc/ssl/private/yourcompany.key"
    }
}

제목에는 거창하게 SASL이라고 적었지만, 삽질 후 알아낸 것은 패스워드 인증으로 SASL을 통한다고 하더라도 RADIUS에서 딱히 해줘야할 건 없더라. LDAPS가 아닌 LDAP을 사용하고자 하면 포트를 636에서 389로 바꿔주고 tls {} 항목을 전부 주석처리 해주면 된다.

이제 RADIUS 설정을 하는데, 건드려야할 파일은 2개 뿐이다. 우선 혹시 모르니 기본 설정을 백업해두자. 그리고나서 아파치 설정하듯 설정파일의 링크를 걸어주면 된다.

cd sites-available
cp default myserver
cd ../sites-enabled
rm -f default
ln -s ../sites-available/myserver ./

myserver 파일을 열면 주석 때문에 내용이 엄청나게 긴데, 원본 설정파일을 백업해뒀으니 여기서는 핵심 내용만 붙여넣자. 아래 설정은 직접 설정해보고 작동이 되는 것을 가져왔다.

server default {
    listen {
    type = auth
        ipaddr = *
        port = 0
        limit {
            max_connections = 16
            lifetime = 0
            idle_timeout = 30
        }
    }
    listen {
        ipaddr = *
        port = 0
        type = acct
        limit {
        }
    }
    authorize {
        if (!control:Auth-Type) {
            ldap
            if ((ok || updated) && User-Password) {
                update {
                    control:Auth-Type := ldap
                }
            }
        }
        expiration
        logintime
    }
    authenticate {
        Auth-Type LDAP {
            ldap
        }
    }
    preacct {
        preprocess
        acct_unique
    }
    accounting {
        detail
        unix
        radutmp
        radutmp
        exec
        attr_filter.accounting_response
    }
    session {
        radutmp
    }
    post-auth {
        exec
        Post-Auth-Type REJECT {
            attr_filter.access_reject
        }
    }
    pre-proxy {
    }
    post-proxy {
        eap
    }
}

마지막으로 clients 파일을 작성할 차례다. clients.conf 파일은 접속하는 유저별로 네트워크를 나눌 수 있는 파일이니, 설정파일을 보고 원하는대로 유저 혹은 네트워크를 나누면 된다.

client your_site {
    ipaddr = * #특정 주소에서만 접속을 허용하고 싶으면 원하는 IP주소를 적으면 된다.
    proto = *
    secret = your_password #RADIUS 접속 패스워드
    require_message_authenticator = no
    limit {
        max_connections = 16 #동시접속자 제한수
        lifetime = 0
        idle_timeout = 30 #초 단위
    }
}

RADIUS 서버를 재시작하고 테스트를 해보자.

# systemctl restart freeradius.service
# radtest ldap_username ldap_password ldap_ip_address 0 site_secret
Sent Access-Request Id 111 from 0.0.0.0:32775 to 192.168.0.1:1812 length 79
         User-Name = "ldap_username"
         User-Password = "ldap_password"
         NAS-IP-Address = 127.0.1.1
         NAS-Port = 0
         Message-Authenticator = 0x00
         Cleartext-Password = "ldap_password"

출력 메시지에서 Received Access-Accept Id 78 from 192.168.0.1:1812 to 0.0.0.0:0 length 20라고 나오면 잘 된 것이며, 만약 아래처럼 Expected Access-Accept got Access-Reject 라고 나오면 제대로 작동하지 않는 것이다.

Sent Access-Request Id 126 from 0.0.0.0:46109 to 127.0.0.1:1812 length 77
Received Access-Reject Id 126 from 127.0.0.1:1812 to 0.0.0.0:0 length 20
(0) -: Expected Access-Accept *got Access-Reject*

이럴 경우 journal -xe나 systemctl status로는 제대로 조사하기가 어렵기 때문에 서비스를 데몬으로 띄우지 말고 명령어로 디버깅 옵션을 키고 보면 무슨 문제인지 바로 알 수 있다.

/usr/sbin/freeradius -X

끝.