`gitlab-sshd`
GitLab v19.5Offering: GitLab Self-Managed
요약
gitlab-sshd는 Go로 작성된 독립형 SSH 서버 입니다. OpenSSH가 제한된 셸 방식을 사용하는 것과 달리 gitlab-sshd는 다음과 같습니다. 구현에 관한 자세한 내용은 블로그 게시물을 참고합니다. OpenSSH에서 gitlab-sshd로 전환을 검토한다면 다음 사항을 고려합니다.
gitlab-sshd는 Go로 작성된 독립형 SSH 서버
입니다. OpenSSH의 경량 대안이며, gitlab-shell 패키지에 포함되어
SSH 작업을 처리합니다.
OpenSSH가 제한된 셸 방식을 사용하는 것과 달리 gitlab-sshd는 다음과 같습니다.
- 멀티 스레드 서버 애플리케이션으로 동작합니다.
- SSH 전송 프로토콜 대신 원격 프로시저 호출(RPC)을 사용합니다.
- OpenSSH보다 메모리를 적게 사용합니다.
- 프록시 뒤에서 실행되는 애플리케이션에 대해 IP 주소 기반 그룹 액세스 제한을 지원합니다.
구현에 관한 자세한 내용은 블로그 게시물을 참고합니다.
OpenSSH에서 gitlab-sshd로 전환을 검토한다면 다음 사항을 고려합니다.
- PROXY 프로토콜:
gitlab-sshd는 PROXY 프로토콜을 지원하므로 HAProxy 같은 프록시 서버 뒤에서 실행할 수 있습니다. 이 기능은 기본적으로 비활성화되어 있으며 활성화할 수 있습니다. - SSH 인증서:
gitlab-sshd는config.yml에 구성한 신뢰할 수 있는 CA 키를 사용해 인스턴스 수준 SSH 인증서 인증을 지원합니다. 자세한 내용은gitlab-sshd를 사용하는 인스턴스 수준 SSH 인증서를 참고합니다. - 2FA 복구 코드:
gitlab-sshd는 2FA 복구 코드 재생성을 지원하지 않습니다.2fa_recovery_codes를 실행하면 다음 오류가 발생합니다.remote: ERROR: Unknown command: 2fa_recovery_codes. 자세한 내용은 논의 내용을 참고합니다. - 알고리즘 구성:
gitlab-sshd는/etc/ssh/sshd_config를 읽지 않습니다. 자세한 내용은 SSH 알고리즘 구성을 참고합니다. - Git 프로토콜 v2:
gitlab-sshd는 추가 구성 없이GIT_PROTOCOL환경 변수를 허용합니다. Git 프로토콜 v2 구성에 설명된AcceptEnv설정은 OpenSSH 에만 적용됩니다.
GitLab Shell의 기능은 Git 작업을 넘어서며, GitLab과의 다양한 SSH 기반 상호 작용에 사용할 수 있습니다.
gitlab-sshd 활성화#
gitlab-sshd를 사용하는 방법은 다음과 같습니다.
다음 절차는 OpenSSH와 다른 포트에서 gitlab-sshd를 활성화합니다.
-
/etc/gitlab/gitlab.rb를 편집합니다.gitlab_sshd['enable'] = true gitlab_sshd['listen_address'] = '[::]:2222' # Adjust the port accordingly -
선택 사항. 기본적으로 Linux 패키지 설치본은
/var/opt/gitlab/gitlab-sshd에 SSH 호스트 키가 없으면gitlab-sshd용으로 호스트 키를 생성합니다. 이 자동 생성을 비활성화하려면 다음 줄을 추가합니다.gitlab_sshd['generate_host_keys'] = false -
파일을 저장하고 GitLab을 재구성합니다.
sudo gitlab-ctl reconfigure
기본적으로 gitlab-sshd는 git 사용자로 실행됩니다. 따라서 gitlab-sshd는
1024보다 낮은 특권 포트 번호에서 실행할 수 없습니다. 즉, 사용자는
gitlab-sshd 포트로 Git에 액세스하거나, SSH 트래픽을 gitlab-sshd 포트로
전달하는 로드 밸런서를 사용해 이를 감춰야 합니다.
새로 생성된 호스트 키가 OpenSSH 호스트 키와 다르기 때문에 사용자에게 호스트 키
경고가 표시될 수 있습니다. 이것이 문제가 된다면 호스트 키 생성을 비활성화하고
기존 OpenSSH 호스트 키를 /var/opt/gitlab/gitlab-sshd로 복사하는 방안을
고려합니다.
다음 절차는 OpenSSH 대신 gitlab-sshd를 사용하도록 전환합니다.
-
gitlab-shell차트의sshDaemon옵션을gitlab-sshd로 설정합니다. 예를 들면 다음과 같습니다.gitlab: gitlab-shell: sshDaemon: gitlab-sshd -
Helm 업그레이드를 수행합니다.
기본적으로 gitlab-sshd는 다음을 수신합니다.
- 포트 22(
global.shell.port)의 외부 요청. - 포트 2222(
gitlab.gitlab-shell.service.internalPort)의 내부 요청.
Helm 차트에서 다른 포트를 구성할 수 있습니다.
SSH 알고리즘 구성#
히스토리
gitlab-sshd는 별도의 SSH 서버이며 /etc/ssh/sshd_config를 읽지 않습니다.
대신 GitLab 설정으로 제공할 알고리즘을 구성합니다.
키 교환 알고리즘, 암호화 방식, 메시지 인증 코드(MAC) 알고리즘, 그리고
클라이언트 인증에 허용되는 공개 키 알고리즘을 설정할 수 있습니다.
이 설정은 gitlab-sshd가 활성화된 경우에만 적용됩니다.
또한 gitlab-sshd가 수신하는 포트에만 적용됩니다.
OpenSSH가 다른 포트에서 Git SSH 트래픽을 처리한다면 해당 포트는
/etc/ssh/sshd_config에서 별도로 구성합니다.
public_key_algorithms에서 알고리즘을 제거하면 영향을 받는 클라이언트가
인증할 수 없습니다.
아래 예시는 ssh-rsa를 제외하므로 SHA-1 RSA 서명만 생성할 수 있는 클라이언트가
영향을 받습니다.
RSA SSH 인증서는 계속 동작합니다. 클라이언트가 이를
rsa-sha2-256-cert-v01@openssh.com 또는 rsa-sha2-512-cert-v01@openssh.com으로
제시하고, 그 기반 알고리즘은 계속 허용되기 때문입니다.
ssh-rsa-cert-v01@openssh.com 으로만 제한된 클라이언트만 영향을 받습니다.
이 변경을 적용하기 전에 클라이언트를 확인합니다.
gitlab-sshd가 제공하는 알고리즘을 제한하는 방법은 다음과 같습니다.
-
/etc/gitlab/gitlab.rb를 편집합니다. 예를 들어 SHA-1을 사용하는 알고리즘을 제외하려면 다음과 같이 설정합니다.gitlab_sshd['kex_algorithms'] = %w(mlkem768x25519-sha256 curve25519-sha256 ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521 diffie-hellman-group16-sha512) gitlab_sshd['macs'] = %w(hmac-sha2-512-etm@openssh.com hmac-sha2-256-etm@openssh.com) gitlab_sshd['public_key_algorithms'] = %w(ssh-ed25519 sk-ssh-ed25519@openssh.com sk-ecdsa-sha2-nistp256@openssh.com ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521 rsa-sha2-256 rsa-sha2-512)SHA-1을 사용하는 기본 암호화 방식은 없으므로
ciphers설정은 변경할 필요가 없습니다. 암호화 방식을 별도로 제한하려면gitlab_sshd['ciphers']를 설정합니다. -
파일을 저장하고 GitLab을 재구성합니다.
sudo gitlab-ctl reconfigure
생성된 구성은 /var/opt/gitlab/gitlab-shell/config.yml의 sshd 섹션에
기록됩니다.
이 설정은 sshDaemon 이 gitlab-sshd로 설정된 경우에만 적용됩니다.
sshDaemon의 기본값은 openssh 입니다.
-
gitlab.gitlab-shell.config옵션을 설정합니다. 예를 들어 SHA-1을 사용하는 알고리즘을 제외하려면 다음과 같이 설정합니다.gitlab: gitlab-shell: sshDaemon: gitlab-sshd config: kexAlgorithms: - mlkem768x25519-sha256 - curve25519-sha256 - ecdh-sha2-nistp256 - ecdh-sha2-nistp384 - ecdh-sha2-nistp521 - diffie-hellman-group16-sha512 macs: - hmac-sha2-512-etm@openssh.com - hmac-sha2-256-etm@openssh.com publicKeyAlgorithms: - ssh-ed25519 - sk-ssh-ed25519@openssh.com - sk-ecdsa-sha2-nistp256@openssh.com - ecdsa-sha2-nistp256 - ecdsa-sha2-nistp384 - ecdsa-sha2-nistp521 - rsa-sha2-256 - rsa-sha2-512 -
Helm 업그레이드를 수행합니다.
각 설정은 해당 알고리즘 유형의 기본 목록을 대체합니다. 설정하지 않은 항목은 기본값을 유지합니다.
기본 알고리즘#
설정을 비워 두면 gitlab-sshd는 GitLab Shell 이 빌드될 때 사용한
golang.org/x/crypto/ssh 패키지의
기본값을 사용합니다.
GitLab 이 해당 의존성을 업데이트하면 기본값도 바뀝니다.
GitLab 18.3 이전에는 GitLab Shell 이 자체 하드코딩 목록을 사용했습니다.
기본값은 허용 범위가 넓으며 SHA-1을 사용하는 알고리즘을 포함합니다. 이를 제외하려면 설정을 명시적으로 구성합니다.
이 설정을 구성하면 다음 동작이 적용됩니다.
- GitLab Shell 이 인식하지 못하는 알고리즘 이름은 오류로 보고되지 않고 목록에서 제거되므로, 실수가 있으면 의도한 것과 다른 목록이 남을 수 있습니다. 변경이 적용되었는지 항상 확인합니다. 자세한 내용은 이슈 870을 참고합니다.
public_key_algorithms의 실수는 동작 방식이 다르고 더 심각합니다. 값이 시작 시점이 아니라 연결마다 검사되므로,gitlab-ctl reconfigure는 성공하고 서버도 시작되지만 클라이언트가 인증할 수 없습니다. 자세한 내용은 이슈 871을 참고합니다.- 구성하지 않은 이름 두 개가 스캔 결과에 나타납니다.
curve25519-sha256을 목록에 넣으면curve25519-sha256@libssh.org가 자동으로 추가됩니다.kex-strict-s-v00@openssh.com은 알고리즘이 아니라 엄격 키 교환 표시자이므로 항상 나타납니다.
GitLab Shell
config.yml.example
파일의 sshd 예시 목록은 형식을 보여 줍니다.
실제 적용되는 기본값은 아닙니다.
변경이 적용되었는지 확인하려면 클라이언트에서 실행 중인 서버를 스캔합니다. 예를 들면 다음과 같습니다.
ssh-audit <hostname> -p <port>
호스트 키 알고리즘#
호스트 키 알고리즘은 직접 구성할 수 없습니다.
gitlab-sshd는 로드한 호스트 키에서 이를 도출하므로, RSA 호스트 키가 있으면 서버가
rsa-sha2-256, rsa-sha2-512, ssh-rsa를 제공합니다.
public_key_algorithms 설정은 클라이언트 인증에만 적용되므로 이 동작을 바꾸지
않습니다.
자세한 내용은 이슈 806을 참고합니다.
서버가 ssh-rsa를 제공하지 않도록 하려면 RSA 호스트 키를 제외합니다.
호스트 키를 제거하면 클라이언트가 보는 호스트 키 지문이 바뀝니다.
사용자에게 호스트 키 경고가 표시되고, 제거된 키에 고정된 클라이언트는
known_hosts 항목이 갱신될 때까지 실패합니다.
이 변경을 적용하기 전에 사용자에게 알립니다.
Linux 패키지 설치본의 경우는 다음과 같습니다.
-
/etc/gitlab/gitlab.rb를 편집합니다.gitlab_sshd['host_keys_glob'] = 'ssh_host_{ecdsa,ed25519}_key' -
파일을 저장하고 GitLab을 재구성합니다.
sudo gitlab-ctl reconfigure
gitlab-sshd는 호스트 키 디렉터리 안에서 패턴을 매칭하며, 기본 디렉터리는
/var/opt/gitlab/gitlab-sshd 입니다.
패턴과 일치하는 파일이 없으면 gitlab-sshd는 시작되지 않습니다.
메트릭#
gitlab-sshd는 gitlab-shell 구성의 web_listen으로 설정한 모니터링 엔드포인트에서
Prometheus 메트릭을 노출합니다.
gitlab-sshd는 해당 주소의 /metrics 경로로 메트릭을 제공합니다.
| 메트릭 | 유형 | 설명 |
|---|---|---|
gitlab_shell_sshd_in_flight_connections |
Gauge | 현재 gitlab-sshd가 처리 중인 연결 수입니다. |
gitlab_shell_sshd_concurrent_limited_sessions_total |
Counter | 동시 세션 한도에 도달한 횟수입니다. |
gitlab_shell_sshd_session_duration_seconds |
Histogram | gitlab-sshd가 처리한 SSH 세션의 지속 시간입니다. |
gitlab_shell_sshd_session_established_duration_seconds |
Histogram | SSH 세션이 수립되기까지의 지연 시간이며, gitlab_sshd 서비스 Apdex의 지연 시간으로 사용됩니다. |
gitlab_sli:shell_sshd_sessions:total |
Counter | 수립된 SSH 세션 수입니다(인증 이후 세션 채널). |
gitlab_sli:shell_sshd_sessions:errors_total |
Counter | 실패한 SSH 세션 수입니다. |
gitlab_sli:shell_sshd_connections:total |
Counter | 인증 단계에 도달한 SSH 연결 수입니다. |
gitlab_sli:shell_sshd_connections:errors_total |
Counter | 서버 측 오류로 실패한 SSH 연결 수입니다. |
세션 수준 및 연결 수준 SLI#
gitlab-sshd는 SSH 안정성을 위해 두 가지 서비스 수준 지표(SLI) 카운터 집합을 노출합니다.
- 세션 수준(
gitlab_sli:shell_sshd_sessions:*)은 인증 이후 세션 채널을 집계합니다. 이 카운터는 인증 단계에서 발생하는 실패를 관측하지 않습니다. - 연결 수준(
gitlab_sli:shell_sshd_connections:*)은 인증 단계에 도달한 각 연결을 집계하며, 인증 단계나 세션 단계에서 발생한 서버 측 오류를 실패로 처리합니다. 세션 수준 카운터와 달리 연결 수준 카운터는authorized_keys조회 오류 같은 인증 단계 실패도 포착합니다. 연결 수준 카운터는 포트 스캐너나 상태 점검처럼 전송 계층 핸드셰이크를 통과하지 못한 연결은 제외합니다.
연결 수준 카운터는 사용자에게 드러나는 실패를 더 넓게 포괄하므로 SSH 안정성 모니터링에 권장되는 신호입니다.
기타 GitLab Shell 메트릭#
gitlab-sshd는 GitLab Shell 이 다른 서비스와 주고받는 상호 작용에 대한 메트릭도
노출합니다.
이 메트릭은 GitLab Shell의 일반 계측에 속하며 SSH 데몬에 한정되지
않습니다.
메트릭은 Gitaly, GitLab 내부 API, Git LFS, Topology Service와의 연결을
포괄합니다.
gitlab-sshd가 SSH 연결을 처리할 때 gitlab-sshd는 이 작업을 자체
프로세스에서 실행하고, 그 결과 카운터를 SSH 메트릭과 동일한 /metrics 엔드포인트에 노출합니다.
gitlab-sshd 대신 OpenSSH를 사용하면 GitLab Shell은 연결마다 단명 프로세스로
실행됩니다.
이 단명 프로세스는 같은 카운터를 증가시키지만 메트릭 엔드포인트를 노출하지 않으므로
카운터를 스크레이핑할 수 없습니다.
| 메트릭 | 유형 | 설명 |
|---|---|---|
gitlab_shell_gitaly_connections_total |
Counter | 수립된 Gitaly 연결 수이며 status(ok 또는 fail)로 레이블이 지정됩니다. |
gitlab_shell_http_requests_total |
Counter | GitLab 내부 API 요청 수이며 code와 method로 레이블이 지정됩니다. |
gitlab_shell_http_request_duration_seconds |
Histogram | GitLab 내부 API 요청의 지연 시간이며 code와 method로 레이블이 지정됩니다. |
gitlab_shell_http_in_flight_requests |
Gauge | 현재 수행 중인 GitLab 내부 API 요청 수입니다. |
lfs_http_connections_total |
Counter | 수립된 Git LFS over HTTP 연결 수입니다. |
lfs_ssh_connections_total |
Counter | 수립된 Git LFS over SSH 연결 수입니다. |
gitlab_shell_topology_connections_total |
Counter | 수립된 Topology Service 연결 수이며 status(ok 또는 fail)로 레이블이 지정됩니다. |
gitlab_shell_topology_requests_total |
Counter | Topology Service Classify 요청 수이며 status(ok 또는 fail)로 레이블이 지정됩니다. |
gitlab_shell_topology_request_duration_seconds |
Histogram | Topology Service Classify 요청의 지연 시간입니다. |
PROXY 프로토콜 지원#
gitlab-sshd 앞에 로드 밸런서가 있으면 GitLab 이 클라이언트 IP 주소 대신 프록시 IP 주소를
보고합니다. 실제 IP 주소를 얻기 위해 gitlab-sshd는
PROXY 프로토콜을 지원합니다.
PROXY 프로토콜을 활성화하는 방법은 다음과 같습니다.
-
/etc/gitlab/gitlab.rb를 편집합니다.gitlab_sshd['proxy_protocol'] = true # Proxy protocol policy ("use", "require", "reject", "ignore"), "use" is the default value gitlab_sshd['proxy_policy'] = "use"gitlab_sshd['proxy_policy']옵션에 관한 자세한 내용은go-proxyproto라이브러리를 참고합니다. -
파일을 저장하고 GitLab을 재구성합니다.
sudo gitlab-ctl reconfigure
-
gitlab.gitlab-shell.config옵션을 설정합니다. 예를 들면 다음과 같습니다.gitlab: gitlab-shell: config: proxyProtocol: true proxyPolicy: "use" -
Helm 업그레이드를 수행합니다.