Motive

리눅스는 태생이 CLI 환경이고, 여전히 많은 이들이 CLI 환경에서 사용하는 OS이지만 때로는 GUI 환경이 불가피할 때도 있다.

RAID 서버의 RAID 구성을 관리하기 위해서 Adaptec 社의 ASM(Adaptec Storage Manager)을 설치한 후 실행하려 했다. 물론 CLI 환경에서도 이런 저런 configuration이 가능은 하지만 ASM을 켜는 편이 훠어어얼씬 편하다. RAID 서버는 저 먼 지하의 서버실에 놓여져 있으므로 보통은 서버에 ssh로 접속한 후 작업을 하게 된다. 최신 버전의 우분투 서버 18은 root 계정의 ssh 접속을 차단한다. (물론 이 차단을 sshd 설정을 바꾸어 풀 수는 있다.) 따라서 유저 계정으로 우선 서버에 접속 후 root 권한을 얻기 위해서 ASM을 sudo를 붙여 실행하거나 suroot 계정으로 전환한 후 실행을 하는 쪽으로 시도하였다. 하지만 다음과 같은 메세지와 함께 GUI 프로그램의 창이 뜨지 않았다.

X11 connection rejected because of wrong authentication.
Exception in thread "main" java.lang.InternalError: Can't connect to X11 window server using 'localhost:12.0' as the value of the DISPLAY variable.
        at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)
        at sun.awt.X11GraphicsEnvironment.access$100(X11GraphicsEnvironment.java:52)
        at sun.awt.X11GraphicsEnvironment$1.run(X11GraphicsEnvironment.java:155)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.awt.X11GraphicsEnvironment.<clinit>(X11GraphicsEnvironment.java:131)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:169)
        at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:68)
        at java.awt.Window.init(Window.java:379)
        at java.awt.Window.<init>(Window.java:432)
        at java.awt.Frame.<init>(Frame.java:403)
        at java.awt.Frame.<init>(Frame.java:368)
        at javax.swing.JFrame.<init>(JFrame.java:163)
        at com.ibm.sysmgt.raidmgr.mgtGUI.Launch.<clinit>(Launch.java:219)
Could not find the main class: com.ibm.sysmgt.raidmgr.mgtGUI.Launch.  Program will exit.

3번 라인 이하인 아래쪽 내용은 ASMjava를 베이스로 작성된 프로그램이라서 자바 관련 에러가 뜨는 것이고 본질과는 상관이 없다. python으로 쓰여진 프로그램이었으면 python의 에러를 뱉었을 것이다. 본질은 X11 접속이 거부당했기 때문에 GUI 창 자체를 띄우지 못하는 상황에 있다. (로컬 환경에서 프로그램을 켜 볼 생각은 애초에 하지도 못했다. 우분투 서버 버전이 설치되어 있어서 데스크톱 환경 자체가 없는 상황이다.)

왜 X11 접속이 거부당할까?

우선 X11의 접속 원리부터 간단하게 짚고 넘어갈 필요가 있다. ssh는 원격으로 쉘을 실행하므로 당연히 GUI와는 상관이 없지만, 요즘은 세상이 좋아져서 X11 forwarding을 통해 클라이언트에서도 윈도우를 띄우는 것이 가능하다. sshX11 forwarding을 지원한다면 ssh 접속을 할 때 클라이언트의 요청에 의해 서버는 별도의 디스플레이 세션을 마련하고, 유저에게 그 세션을 할당한다. 어느 세션을 할당 받았는지는 DISPLAY 환경 변수를 출력해 보면 알 수 있다.

$ echo $DISPLAY
localhost:10.0

형식은 [호스트네임:디스플레이번호.스크린번호]의 방식이며, 로컬 디스플레이는 0번부터 시작하고 ssh 세션을 위한 X서버에게는 보통 10번부터 번호가 부여된다. (물론 이 시작번호도 sshd 설정에서 바꿀 수 있다.) 엥간하면 디스플레이 매니저가 ssh가 자동으로 번호를 붙여주고 다 해주기 때문에 이 DISPLAY 환경변수를 직접 손볼 일은 거의 없다.

X윈도우를 위한 담당일진(예를 들면 localhost:10.0)이 달라붙었다고 그냥 바로 창을 원격에서 띄울 수 있는 것은 아니고 정해진 절차에 따른 인증을 통과해야 한다. 클라이언트가 ssh로 접속할 때 MIT Magic Cookie(MMC)라는 것을 랜덤으로 생성하여 서버에 보내준다. MMC라는 게정확히 뭔지 이해할 필요는 없다. 쉽게 말해 비밀번호 같은 것(쿠키)을 서버와 클라이언트가 똑같이 복사해서 가지고 있다고 이해하자. xauth라는 프로그램은 그 쿠키를 유저의 홈의 .Xauthority파일에 쿠키 내용을 추가, 삭제, 리스트를 출력하는 유틸리티로, 자신의 홈의 .Xauthority를 텍스트 에디터로 열어보아도 읽을 수 있고, xauth list라는 커맨드를 통해서도 서버가 가지고 있는 쿠키 목록을 확인할 수 있다.

$ xauth list
servername/unix:10  MIT-MAGIC-COOKIE-1  blahblahblah...

(서버이름과 쿠키는 다른 텍스트로 대체되어 있음.) 따라서 X11 포워딩을 요청할 때 서버가 저 쿠키를 들고 가서 클라이언트에 찾아간 후 쿠키를 대조하여 일치하면 클라이언트가 그때서야 창을 띄울 수 있는 것이다.

저렇게 쿠키가 서버에 저장되어 있는데, 일부러 저 쿠키를 지워버려 보자. 단순히 자신의 홈 디렉토리의 .Xauthority를 지우면 된다.

rm ~/.Xauthority

자 이제 아무 GUI 프로그램이나 띄워보자. gedit, firefox 등 어떤 프로그램이든 좋다. 예를 들어 gedit을 실행하면 다음과 같은 메세지와 함께 창이 뜨지 않는다.

X11 connection rejected because of wrong authentication.
Unable to init server: Could not connect: Connection refused

(gedit:9901): Gtk-WARNING **: 08:07:23.754: cannot open display: localhost:10.0

어디서 많이 봤던 메세지이다. 쿠키가 없기 때문에 (혹은 쿠키와 일치하지 않기 때문에) 서버가 클라이언트에 X11 접속을 시도했으나 거절을 당해버린 것. 여기까지의 상황을 이해하고 나니 비로소 왜 내가 ASM을 실행할 수 없었는지 이해가 가기 시작한다.

내가 서버에 ssh로 접속을 했을 때까지는 X11 인증에 아무 문제가 없었다. 문제는 su 커맨드(substitute user)를 통해 다른 계정으로 전환했을 때부터 발생한다. root 계정이든 다른 계정이든 본질은 다르지 않다. 처음부터 sshroot 계정을 접속하지 못해 su라는 우회를 통해 root 계정의 쉘을 켰던 것이 문제였다. su를 통해 A계정에서 B계정으로 전환하는 상황을 가정한다면 다음 두 가지 문제가 생긴다.

  1. B의 DISPLAY 환경변수는 su로 전환하기 이전의 A계정의 변수를 그대로 가져온다. (어느 변수는 그대로 가져오고 어느 변수는 재설정하는지는 man su를 읽어볼 것. 또는 https://storycompiler.tistory.com/44 에 정리된 내용을 확인.)
  2. B는 ssh로 쉘을 켠 것이 아니기 때문에 X11 포워딩의 과정을 거치지 않았으므로 클라이언트의 쿠키 정보를 갖고 있지 않다.

이 상황에서 B계정으로 GUI를 띄우려 한다면? 쿠키도 없는 주제에 A계정의 디스플레이를 사용해서 창을 띄우려 했으니 클라이언트 입장에선 당연히 거부해 버린다.

Solution

그렇다면 이 상황을 해결하기 위해서는? 두 가지의 방법이 있을 수 있겠다.

  1. root 계정의 ssh 접속을 허용해 버린다. 이러면 root 계정이 직접 ssh 접속을 하면서 쿠키를 교환할 것이므로 X11 인증에 문제가 생기지 않는다.
  2. 일반 계정으로 ssh 접속을 하고 suroot 계정으로 넘어가는 대신에, 일반 계정의 쿠키를 root 계정에게도 알려줘서 X11 포워딩에 써먹게 한다.

1번 해결책은 간단하고 직관적인 대신에 혹자는 보안상 쫌 거시기할 수 있을 듯 하다. 그게 꺼림칙한 이들을 위해, 2번 해결책은 다음과 같은 트릭을 사용한다. 우선 평소처럼 일반 계정으로 ssh 접속을 하고 xauth list를 통해 쿠키를 출력해 둔다.

$ xauth list
호스트이름/unix:10  MIT-MAGIC-COOKIE-1  어쩌고저쩌고

그 다음에 suroot 계정으로 전환한다. 이제 일반 계정의 쿠키를 root 계정에게도 알려준다. 비밀번호를 살짝 귀띔해주는 식이다. xauth를 통해 바로 위에서 얻은 쿠키를 root.Xauthority 파일에 추가한다.

xauth add 호스트이름/unix:10  MIT-MAGIC-COOKIE-1  어쩌고저쩌고

이런 식으로 비밀번호(쿠키)를 유출하면 root 계정도 일반 계정의 X11 forwarding을 자유자재로 쓸 수 있게 된다.

Conclusion

su로 유저 전환을 했을 때 X11 포워딩이 안 되는 현상은 매우 당연해 보이며 보안상 안돼야 하는 방향이 맞는 듯 하다. RAID 설정은 1년에도 몇 번 할 까말까한 드문 작업이므로 굳이 root 계정의 ssh 접속을 허용하기 보다는 임시로 일반 계정의 쿠키를 가져다가 사용하는 방향이 바람직해 보인다. 물론 작업 후에는 쿠키를 비워주는 것이 좋을 것이다.


0개의 댓글

답글 남기기

아바타 플레이스홀더