Home SSH Key Sharing
Post
Cancel

SSH Key Sharing

Hyper-v 쿠버네티스 클러스터에서 각 서버에 접근할 때 비밀번호 없이 로그인하기 위해 ssh key를 생성하고 key를 각 서버에 자동 배포하기 위해 작성한 쉘스크립트 코드이다.

SSH Key


서버에 접속할 때 비밀번호 대신 key를 제출하는 방식이다.

사용하는 목적

  • 비밀번호보다 높은 수준의 보안을 필요로 할 때
  • 로그인 없이 자동으로 서버에 접속 할 때

SSH Key가 동작하는 방식


SSH Key는 공개키(public key)와 비공개 키(private key)로 이루어 진다.

키를 생성하면 공개키와 비공개키가 만들어진다. 이 중에 비공개키는 로컬 머신에 위치해야 하고, 공개키는 리모트 머신에 위치해야 한다. (로컬 호스트는 SSH Client, 원격 호스트는 SSH Server가 설치된 서버를 의미한다)

로컬 호스트의 어카운트에 있는 ~/.ssh/id_rsa.pub 키파일의 내용을 원격 호스트 어카운트의 ~/.ssh 디렉토리에 있는 authorized_keys 에 복사한다.

정리하면, SSH Server의 authorized_keys의 내용이 SSH Client의 id_rsa.pub 파일과 같아야 한다. ssh 접속을 할 때 id_rsa 파일과 authorized_keys 파일의 내용을 비교한다.

아래와 같이 서버에 public key를 카피해 놓았다면 원격 호스트에 로그인 할 어카운트의 암호 없이 로그인이 가능하다.

Untitled

[ssh_key_sharing.sh]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
export CLUSTER_HOSTS=(vm1 vm2 vm3 vm4 vm5 vm6 vm7 vm8 vm9)
export HOME_DIR_PATH=/home/$USER

# sshd_config 변경
for i in ${!CLUSTER_HOSTS[*]}; do ssh woobin@${CLUSTER_HOSTS[$i]} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "sudo dnf install -y sshpass && sudo sed -i -e 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config && sudo systemctl restart sshd" &> /dev/null; done

# ssh key 생성
echo -e ">> Enter Password:"; read -s PASSWD; for i in ${!CLUSTER_HOSTS[*]}; do echo "i[$i]: [${CLUSTER_HOSTS[$i]}]"; sshpass -p $PASSWD ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no woobin@${CLUSTER_HOSTS[$i]} "mkdir -p $HOME_DIR_PATH/.ssh; echo -e 'n\n' | ssh-keygen -t rsa -f $HOME_DIR_PATH/.ssh/id_rsa -q -N ''; cp $HOME_DIR_PATH/.ssh/id_rsa.pub $HOME_DIR_PATH/.ssh/authorized_keys; chmod 700 $HOME_DIR_PATH/.ssh" &> /dev/null; done

# ssh key 공유
echo -e ">> Enter Password:"; read -s PASSWD; for i in ${!CLUSTER_HOSTS[*]}; do echo "i[$i]: [${CLUSTER_HOSTS[$i]}]"; for j in ${!CLUSTER_HOSTS[*]}; do echo "j[$j]: [${CLUSTER_HOSTS[$i]}] -> [${CLUSTER_HOSTS[$j]}]"; sshpass -p $PASSWD ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no woobin@${CLUSTER_HOSTS[$i]} "sshpass -p $PASSWD ssh-copy-id -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no woobin@${CLUSTER_HOSTS[$j]} &> /dev/null" &> /dev/null; done; done

# 체크
for i in ${CLUSTER_HOSTS[*]}; do ssh ${CLUSTER_HOSTS[$i]} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "ls -al .ssh"; done

코드 설명


ssh key 생성


1
echo -e ">> Enter Password:"; read -s PASSWD; for i in ${!CLUSTER_HOSTS[*]}; do echo "i[$i]: [${CLUSTER_HOSTS[$i]}]"; sshpass -p $PASSWD ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no woobin@${CLUSTER_HOSTS[$i]} "mkdir -p $HOME_DIR_PATH/.ssh; echo -e 'n\n' | ssh-keygen -t rsa -f $HOME_DIR_PATH/.ssh/id_rsa -q -N ''; cp $HOME_DIR_PATH/.ssh/id_rsa.pub $HOME_DIR_PATH/.ssh/authorized_keys; chmod 700 $HOME_DIR_PATH/.ssh" &> /dev/null; done

아래부터는 각 부분에 대한 설명입니다.

1
echo -e ">> Enter Password:";
  • ”» Enter Password:” 메시지를 출력합니다.
1
read -s PASSWD;
  • 사용자로부터 비밀번호를 읽어서 PASSWD 변수에 저장합니다. s 옵션은 입력한 비밀번호가 화면에 표시되지 않도록 합니다.
1
`for i in ${!CLUSTER_HOSTS[*]}; do`
  • 배열 CLUSTER_HOSTS의 모든 인덱스를 순회하는 루프를 시작합니다.
1
echo "i[$i]: [${CLUSTER_HOSTS[$i]}]";
  • 순회 중인 인덱스 i와 해당 인덱스에 위치한 CLUSTER_HOSTS 배열의 요소를 출력합니다.
1
sshpass -p $PASSWD ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ${CLUSTER_HOSTS[$i]}
  • sshpass 명령어를 사용하여 비밀번호를 제공하고, ssh 명령을 통해 원격 호스트에 연결합니다.
  • $PASSWD 변수에 저장된 비밀번호를 p 옵션으로 전달합니다.
  • -o UserKnownHostsFile=/dev/null 옵션은 호스트 키를 known_hosts 파일에 저장하지 않도록 합니다. /dev/null은 특수 파일로, 데이터를 버리는데 사용됩니다.
  • -o StrictHostKeyChecking=no 옵션은 호스트 키의 유효성을 검사하지 않도록 합니다. 일반적으로 클라이언트가 원격 서버의 호스트 키와 일치하는지 확인하며, 일치하지 않으면 경고를 표시하고 연결을 거부합니다. 그러나 이 옵션을 사용하면 호스트 키 검사를 건너뛰고 연결을 허용하게 됩니다.
  • ${CLUSTER_HOSTS[$i]}는 현재 순회 중인 인덱스 i에 해당하는 원격 호스트 주소를 사용합니다.
1
"mkdir -p $HOME_DIR_PATH/.ssh; echo -e 'n\n' | ssh-keygen -t rsa -f $HOME_DIR_PATH/.ssh/id_rsa -q -N ''; cp $HOME_DIR_PATH/.ssh/id_rsa.pub $HOME_DIR_PATH/.ssh/authorized_keys; chmod 700 $HOME_DIR_PATH/.ssh" &> /dev/null;
  • 원격 호스트에 로그인한 후 수행할 명령어들입니다. 여러 명령어를 세미콜론(;)으로 구분하여 순차적으로 실행합니다.
  • mkdir -p $HOME_DIR_PATH/.ssh;은 원격 호스트에서 .ssh 디렉토리를 생성합니다. p 옵션은 이미 디렉토리가 존재하면 무시하도록 합니다.
  • echo -e 'n\n' | ssh-keygen -t rsa -f $HOME_DIR_PATH/.ssh/id_rsa -q -N '';
    • echo -e 'n\n' |: ssh-keygen 명령을 실행할 때 기존 키 파일이 존재하는 경우에 대한 덮어쓰기 여부를 묻는 메시지가 나오는 것을 피하는 것입니다. echo -e ‘n\n’ 명령을 통해 “n”이라는 문자를 출력하고 줄 바꿈을 추가하여, ssh-keygen 명령이 “n” 입력을 받아 덮어쓰기를 거부하도록 하는 것입니다.
    • -t rsa: RSA 알고리즘을 사용하여 키를 생성한다는 것을 나타냅니다. RSA는 공개키 암호화 방식으로 널리 사용됩니다.
    • -f $HOME_DIR_PATH/.ssh/id_rsa: 생성할 개인키와 공개키의 파일 이름과 경로를 지정합니다.
      • ssh key가 저장되는 기본 경로는 로그인 한 사용자의 홈디렉토리 아래에 .ssh입니다. SSH Client는 기본적으로 이 디렉토리에 있는 키를 이용해서 인증을 시도합니다. 여기서는 위에서 지정한 HOME_DIR_PATH/.ssh 경로에 생성하며, 생성되는 파일은 아래와 같습니다.
      • id_rsa: private key, 절대로 타인에게 노출되면 안된다.
      • id_rsa.pub: public key, 접속하려는 리모트 머신의 authorized_keys에 입력한다.
      • authorized_keys: .ssh 디렉토리 아래에 위치하면서 id_rsa.pub 키의 값을 저장한다.
    • -q: quiet 모드로 작동하게 합니다. 이 옵션을 사용하면 사용자 입력을 최소화하고 진행 과정에서 메시지를 표시하지 않습니다.
    • -N '': 개인키에 설정할 암호를 지정합니다. 여기서는 빈 문자열('')을 사용하여 암호를 설정하지 않도록 합니다. 암호를 설정하지 않으면 SSH 키를 사용할 때 암호를 입력하지 않아도 됩니다.
  • cp $HOME_DIR_PATH/.ssh/id_rsa.pub $HOME_DIR_PATH/.ssh/authorized_keys;은 공개 키를 authorized_keys 파일에 복사합니다. 이렇게 하면 비밀번호 없이 원격 호스트에 로그인할 수 있게 됩니다.
  • chmod 700 $HOME_DIR_PATH/.ssh는 매우 중요한 보안 정보가 담긴 디렉토리 입니다. 따라서 퍼미션 설정을 해줘야 합니다. 해당 디렉토리가 소유자만 읽기, 쓰기, 실행이 가능하도록 합니다.
  • &> /dev/null;는 모든 출력을 무시하고 실행 결과를 /dev/null로 보냅니다. 즉, 실행 결과를 출력하지 않습니다.

ssh key 공유


1
echo -e ">> Enter Password:"; read -s PASSWD; for i in ${!CLUSTER_HOSTS[*]}; do echo "i[$i]: [${CLUSTER_HOSTS[$i]}]"; for j in ${!CLUSTER_HOSTS[*]}; do echo "j[$j]: [${CLUSTER_HOSTS[$i]}] -> [${CLUSTER_HOSTS[$j]}]"; sshpass -p $PASSWD ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no woobin@${CLUSTER_HOSTS[$i]} "sshpass -p $PASSWD ssh-copy-id -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no woobin@${CLUSTER_HOSTS[$j]} &> /dev/null" &> /dev/null; done; done

아래부터는 각 부분에 대한 설명입니다.

1
for i in ${!CLUSTER_HOSTS[*]}; do echo "i[$i]: [${CLUSTER_HOSTS[$i]}]"; for j in ${!CLUSTER_HOSTS[*]}; do echo "-- j[$j]: [${CLUSTER_HOSTS[$i]}] -> [${CLUSTER_HOSTS[$j]}]";
  • 중첩 for-loop를 통해 모든 클러스터에 대해 진행합니다.
1
sshpass -p $PASSWD ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ${CLUSTER_HOSTS[$i]}
  • 현재 i번째 인덱스에 해당하는 원격 호스트에서 아래의 작업을 진행합니다.
1
"sshpass -p $PASSWD ssh-copy-id -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ${CLUSTER_HOSTS[$j]} &> /dev/null" &> /dev/null;
  • ssh-copy-id: SSH 공개 키를 원격 호스트에 복사합니다.
  • -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no: 호스트 키 확인 및 기록을 하지 않도록 설정합니다.
  • &> /dev/null: 표준 출력과 표준 에러를 /dev/null로 리다이렉트하여 출력을 무시합니다.
This post is licensed under CC BY 4.0 by the author.