Kerberos 방식은 다양한 프로토콜 메시지를 디코딩하기 위해 여러 가지 DTrace 프로브를 지원합니다. 목록은 Appendix A, Kerberos용 DTrace 프로브를 참조하십시오. DTrace 프로브는 권한 있는 사용자가 암호화되지 않은 Kerberos 및 응용 프로그램 데이터를 쉽게 찾아볼 수 있도록 허용함으로써 다른 프로토콜 검사자보다 확실한 장점을 제공합니다.
다음 예에서는 Kerberos DTrace 프로브를 사용하여 볼 수 있는 정보를 보여 줍니다.
예 8-1 DTrace를 사용하여 Kerberos 메시지 추적다음 스크립트는 DTrace 프로브를 사용하여 시스템에서 전송하고 수신한 Kerberos 메시지에 대한 세부 정보를 표시합니다. 표시되는 필드는 krb_message-recv 및 krb_message-send 프로브에 지정된 구조에 따라 달라집니다. 자세한 내용은 Kerberos DTrace 프로브의 정의를 참조하십시오.
kerberos$target:::krb_message-recv { printf("<- krb message recved: %s\n", args[0]->krb_message_type); printf("<- krb message remote addr: %s\n", args[1]->kconn_remote); printf("<- krb message ports: local %d remote %d\n", args[1]->kconn_localport, args[1]->kconn_remoteport); printf("<- krb message protocol: %s transport: %s\n", args[1]->kconn_protocol, args[1]->kconn_type); } kerberos$target:::krb_message-send { printf("-> krb message sent: %s\n", args[0]->krb_message_type); printf("-> krb message remote addr: %s\n", args[1]->kconn_remote); printf("-> krb message ports: local %d remote %d\n", args[1]->kconn_localport, args[1]->kconn_remoteport); printf("-> krb message protocol: %s transport: %s\n", args[1]->kconn_protocol, args[1]->kconn_type); printf("\n"); } kerberos$target:::krb_error-read { printf("<- krb error code: %s\n", args[1]->kerror_error_code); printf("<- krb error client: %s server: %s\n", args[1]->kerror_client, args[1]->kerror_server); printf("<- krb error e-text: %s\n", args[1]->kerror_e_text); printf("\n"); }
위의 스크립트를 명령줄에서 호출하거나 krb5kdc 데몬을 사용하여 호출할 수 있습니다. 다음은 명령줄에서 krb-dtrace.d라는 스크립트를 호출하는 방법을 보여 주는 예입니다. 이 명령은 Kerberos가 메시지를 전송 및 수신하도록 합니다. LD_NOLAZYLOAD=1은 Kerberos DTrace 프로브가 포함된 Kerberos mech_krb5.so 라이브러리를 로드하는 데 필요합니다.
# LD_NOLAZYLOAD=1 dtrace -s ./krb\-dtrace.d -c kinit dtrace: script './krb-dtrace' matched 4 probes kinit: Client 'root@DEV.ORACLE.COM' not found in Kerberos database while g etting initial credentials dtrace: pid 3750 has exited CPU ID FUNCTION:NAME 2 74782 k5_trace_message_send:krb_message-send -> krb message sent: KR B_AS_REQ(10) -> krb message remote addr: 10.229.168.163 -> krb message ports: local 62029 remote 88 -> krb message protocol: ipv4 transport: udp 2 74781 k5_trace_message_recv:krb_message-recv <- krb message recved: KRB_ERROR(30) <- krb message remote addr: 10.229.168.163 <- krb message ports: local 62029 remote 88 <- krb message protocol: ipv4 transport: udp 2 74776 krb5_rd_error:krb_error-read <- krb error code: KDC_ERR_C_ PRINCIPAL_UNKNOWN(6) <- krb error client: root@DEV.ORACLE.COM server: krbtgt/DEV.ORACLE.COM@DEV .ORACLE.COM <- krb error e-text: CLIENT_NOT_FOUND
krb5kdc 데몬에 스크립트를 사용하려면 svc:/network/security/krb5kdc:default 서비스가 사용으로 설정되고 온라인 상태여야 합니다. 다음 명령은 LD_NOLAZYLOAD=1을 사용하지 않는데 mech_krb5.so 라이브러리가 krb5kdc 데몬을 로드하기 때문입니다.
# dtrace -s ./krb\-dtrace.d -p $(pgrep -x krb5kdc)예 8-2 DTrace를 사용하여 Kerberos 사전 인증 유형 보기
다음 예에서는 클라이언트가 선택한 사전 인증을 보여줍니다. 첫번째 단계는 다음과 같은 DTrace 스크립트를 만드는 것입니다.
cat krbtrace.d kerberos$target:::krb_message-recv { printf("<- krb message recved: %s\n", args[0]->krb_message_type); printf("<- krb message remote addr: %s\n", args[1]->kconn_remote); printf("<- krb message ports: local %d remote %d\n", args[1]->kconn_localport, args[1]->kconn_remoteport); printf("<- krb message protocol: %s transport: %s\n", args[1]->kconn_protocol, args[1]->kconn_type); } kerberos$target:::krb_message-send { printf("-> krb message sent: %s\n", args[0]->krb_message_type); printf("-> krb message remote addr: %s\n", args[1]->kconn_remote); printf("-> krb message ports: local %d remote %d\n", args[1]->kconn_localport, args[1]->kconn_remoteport); printf("-> krb message protocol: %s transport: %s\n", args[1]->kconn_protocol, args[1]->kconn_type); printf("\n"); } kerberos$target:::krb_kdc_req-make { printf("-> krb kdc_req make msg type: %s\n", args[0]->krb_message_type); printf("-> krb kdc_req make pre-auths: %s\n", args[1]->kdcreq_padata_types); printf("-> krb kdc_req make auth data: %s\n", args[1]->kdcreq_authorization_data); printf("-> krb kdc_req make client: %s server: %s\n", args[1]->kdcreq_client, args[1]->kdcreq_server ); } kerberos$target:::krb_kdc_req-read { /* printf("<- krb kdc_req msg type: %s\n", args[0]->krb_message_type); */ printf("<- krb kdc_req client: %s server: %s\n", args[1]->kdcreq_client, args[1]->kdcreq_server ); printf("\n"); } kerberos$target:::krb_kdc_rep-read { /* printf("<- krb kdc_rep msg type: %s\n", args[0]->krb_message_type); */ printf("<- krb kdc_rep client: %s server: %s\n", args[1]->kdcrep_client, args[1]->kdcrep_enc_server ); printf("\n"); } kerberos$target:::krb_ap_req-make { printf("-> krb ap_req make server: %s client: %s\n", args[2]->kticket_server, args[2]->kticket_enc_client ); } kerberos$target:::krb_error-read { printf("<- krb error code: %s\n", args[1]->kerror_error_code); printf("<- krb error client: %s server: %s\n", args[1]->kerror_client, args[1]->kerror_server); printf("<- krb error e-text: %s\n", args[1]->kerror_e_text); printf("\n"); }
그런 다음 다음 명령을 입력하여 Kerberos 시스템에서 권한 있는 사용자로 krbtrace.d 스크립트를 실행합니다.
# LD_BIND_NOW=1 dtrace -qs krbtrace.d -c "kinit -k" . . -> krb kdc_req make pre-auths: FX_COOKIE(133) ENC_TIMESTAMP(2) REQ_ENC_PA_REP(149)
사전 인증 유형이 출력 결과에 표시됩니다. 다양한 사전 인증 유형에 대한 자세한 내용은 RFC 4120을 참조하십시오.
예 8-3 DTrace를 사용하여 Kerberos 오류 메시지 덤프# dtrace -n 'krb_error-make { printf("\n{"); printf("\n\tctime = %Y", (uint64_t)(args[1]->kerror_ctime * 1000000000)); printf("\n\tcusec = %d", args[1]->kerror_cusec); printf("\n\tstime = %Y", (uint64_t)(args[1]->kerror_stime * 1000000000)); printf("\n\tsusec = %d", args[1]->kerror_susec); printf("\n\terror_code = %s", args[1]->kerror_error_code); printf("\n\tclient = %s", args[1]->kerror_client); printf("\n\tserver = %s", args[1]->kerror_server); printf("\n\te_text = %s", args[1]->kerror_e_text); printf("\n\te_data = %s", ""); printf("\n}"); }' dtrace: description 'krb_error-make ' matched 1 probe CPU ID FUNCTION:NAME 0 78307 krb5_mk_error:krb_error-make { ctime = 2012 May 10 12:10:20 cusec = 0 stime = 2012 May 10 12:10:20 susec = 319090 error_code = KDC_ERR_C_PRINCIPAL_UNKNOWN(6) client = testuser@EXAMPLE.COM server = krbtgt/EXAMPLE.COM@EXAMPLE.COM e_text = CLIENT_NOT_FOUND e_data = }예 8-4 DTrace를 사용하여 SSH 서버에 대한 서비스 티켓 보기
# LD_PRELOAD_32=/usr/lib/gss/mech_krb5.so.1 dtrace -q -n ' kerberos$target:::krb_kdc_req-make { printf("kdcreq_server: %s",args[1]->kdcreq_server); }' -c "ssh local@four.example.com" -o dtrace.out Last login: Wed Sep 10 10:10:20 2014 Oracle Solaris 11 X86 July 2014 $ ^D # cat dtrace.out kdcreq_server: host/four.example.com@EXAMPLE.COM예 8-5 초기 TGT를 요청할 때 DTrace를 사용하여 사용할 수 없는 KDC의 주소 및 포트 보기
# LD_BIND_NOW=1 dtrace -q -n ' kerberos$target:::krb_message-send { printf("%s:%d\n",args[1]->kconn_remote, args[1]->kconn_remoteport) }' -c "kinit local4" 10.10.10.14:88 10.10.10.14:750 10.10.10.14:88 10.10.10.14:750 10.10.10.14:88 10.10.10.14:750 kinit(v5): Cannot contact any KDC for realm 'EXAMPLE.COM' while getting initial credentials예 8-6 DTrace를 사용하여 Kerberos 주체의 요청 보기
# LD_BIND_NOW=1 dtrace -qs /opt/kdebug/mykdtrace.d \ -c 'kadmin -p kdc/admin -w test123 -q listprincs' Authenticating as principal kdc/admin with password. krb kdc_req msg type: KRB_AS_REQ(10) krb kdc_req make client: kdc/admin@TEST.NET server: kadmin/interop1.example.com@TEST.NET krb message sent: KRB_AS_REQ(10) krb message recved: KRB_ERROR(30) Err code: KDC_ERR_PREAUTH_REQUIRED(25) Err msg client: kdc/admin@TEST.NET server: kadmin/interop1.example.com@TEST.NET Err e-text: NEEDED_PREAUTH krb kdc_req msg type: KRB_AS_REQ(10) krb kdc_req make client: kdc/admin@TEST.NET server: kadmin/interop1.example.com@TEST.NET krb message sent: KRB_AS_REQ(10) krb message recved: KRB_AS_REP(11) kadmin: Database error! Required KADM5 principal missing while initializing kadmin interface krb kdc_req msg type: KRB_AS_REQ(10) krb kdc_req make client: kdc/admin@TEST.NET server: kadmin/interop2.example.com@TEST.NET krb message sent: KRB_AS_REQ(10) krb message recved: KRB_ERROR(30) Err code: KDC_ERR_S_PRINCIPAL_UNKNOWN(7) Err msg client: kdc/admin@TEST.NET server: kadmin/interop2.example.com@TEST.NET Err e-text: SERVER_NOT_FOUND krb kdc_req msg type: KRB_AS_REQ(10) krb kdc_req make client: kdc/admin@TEST.NET server: kadmin/interop2.example.com@TEST.NET
다음은 위의 출력을 생성하기 위해 사용된 스크립트입니다.
kerberos$target:::krb_message-recv { printf("krb message recved: %s\n", args[0]->krb_message_type); } kerberos$target:::krb_message-send { printf("krb message sent: %s\n", args[0]->krb_message_type); } kerberos$target:::krb_kdc_req-make { printf("krb kdc_req msg type: %s\n", args[0]->krb_message_type); printf("krb kdc_req make client: %s server: %s\n", args[1]->kdcreq_client, args[1]->kdcreq_server ); } kerberos$target:::krb_ap_req-make { printf("krb ap_req make server: %s client: %s\n", args[2]->kticket_server, args[2]->kticket_enc_client ); } kerberos$target:::krb_error-read { printf("Err code: %s\n", args[1]->kerror_error_code); printf("Err msg client: %s server: %s\n", args[1]->kerror_client, args[1]->kerror_server); printf("Err e-text: %s\n", args[1]->kerror_e_text); }