원본 게시물 : http://coffeenix.net/board_view.php?bd_code=1716
제 목 : 일반유저가 1024이하 포트를 사용하려면
작성자 : 좋은진호(truefeel, http://coffeenix.net/ )
작성일 : 2010.10.26(화)
리눅스/유닉스 기본 환경에서는 1024 이하 포트(privileged ports)는 root만 사용할 수가 있다. OS별로 각각 다음 기능을 사용하면 일반유저가 1024이하 포트를 사용할 수 있다.
1) FreeBSD : MAC 인증 매커니즘 (FreeBSD 5.x 이상)
2) Linux : capabilities 설정 (File capabilities를 설정하기 위해서는 커널 2.6.24 이상)
3) Solaris : RBAC로 권한 부여 (Solaris 8 이상)
1. FreeBSD에서 MAC 모듈 로딩
FreeBSD에서는 커널의 MAC(Mandatory Access Control) 인증 매커니즘을 사용하면 일반유저가 1024이하 포트 bind를 쉽게 처리할 수 있다. 먼저 MAC portacl 모듈을 로딩한다.
# kldload mac_portacl # kldstat Id Refs Address Size Name 1 4 0xc0400000 b7ffe8 kernel 2 1 0xca62f000 3000 mac_portacl.ko |
부팅때 자동으로 로딩되도록 /boot/loader.conf에 mac_portacl_load="YES" 를 추가한다. 모듈 로딩시 syslog에는 다음과 같은 로그가 남는다.
Oct 22 14:04:29 ?????? kernel: Security policy loaded: TrustedBSD MAC/portacl (mac_portacl) |
만약 모듈 로딩시 다음과 같은 에러가 생겼다면 커널에서 MAC 모듈을 지원하지 않는 경우이다.
# kldload mac_portacl kldload: can't load mac_portacl: No such file or directory |
이 때 /var/log/messages 에는 다음과 같이 로그가 남는다.
Oct 22 13:17:26 ?????? kernel: KLD mac_portacl.ko: depends on kernel_mac_support - not available |
커널 설정 파일에 다음을 추가하고 재컴파일한다. FreeBSD 8.x부터는 기본 포함되어 있다.
options MAC |
sysctl로 관련 속성들을 살펴보자.
# sysctl security.mac security.mac.labeled: 0 security.mac.max_slots: 4 security.mac.version: 4 security.mac.mmap_revocation_via_cow: 0 security.mac.mmap_revocation: 1 security.mac.portacl.rules: <-- 여기서 부터 모듈 로딩 후 추가된 설정 security.mac.portacl.port_high: 1023 security.mac.portacl.autoport_exempt: 1 security.mac.portacl.suser_exempt: 1 security.mac.portacl.enabled: 1 |
2. FreeBSD에서 일반유저가 1024이 bind하는 예
999포트를 uid 1005가 실행할 수 있도록 해보자.
# sysctl security.mac.portacl.rules=uid:1005:tcp:999 security.mac.portacl.rules: -> uid:1005:tcp:999 [ UID 1005 일반 유저로 실행 ] % nc -l 999 (테스트를 위해 nc명령을 사용했다. CentOS는 동일한 옵션이고, 데비안 또는 우분투는 nc -l -p 999) nc: Operation not permitted |
그런데, 권한이 없다고 한다. 그렇다. 기존의 유닉스 bind 제한 설정을 해제해야 한다. reserved port 최대치를 0으로 바꾸거나 998(999포트를 일반 유저가 오픈할 것이므로 998임)로 바꾼다. 998로 설정했다면, 998까지는 기존의 유닉스 bind 제한 설정을 따르겠다는 것이다.
# sysctl net.inet.ip.portrange.reservedhigh net.inet.ip.portrange.reservedhigh: 1023 # sysctl net.inet.ip.portrange.reservedhigh=998 net.inet.ip.portrange.reservedhigh: 1023 -> 998 |
만약 UID 1005가 999포트와 1000포트를 모두 사용할 수 있게 하려면 다음과 같이 설정한다.
# sysctl security.mac.portacl.rules=uid:1005:tcp:999,uid:1005:tcp:1000 |
3. Linux에서 setcap 명령으로 capabilities 설정
리눅스의 capabilities 설정을 통해서 일반 유저가 1024이하 포트 사용이 가능하다. capabilities란 무엇일까? 전통적인 유닉스/리눅스에서는 root가 모든 권한을 가진다. 일반유저가 root의 일부 권한을 갖기 위해서는 SetUID/SetGID나 sudo 등 기초적인 방법으로 권한을 부여할 수 밖에 없었다. 하지만 capabilities는 root의 권한을 세분화(커널 모듈 load/remove, 파일 소유자/소유그룹 변경, kill권한, ping 허용(ICMP허용), 리부팅 등)하여, 일반 유저도 root의 다양한 권한을 갖도록 만든 보안 모델이다. 일반 유저에게 패킷 모니터링툴을 사용할 수 있도록 허용할 수 있다. PAM 모듈을 사용하면 user를 지정하여 권한 부여도 할 수 있다.
capabilities은 커널에서 지원해야 하며, File capabilities를 위해서는 2.6.24이상을 사용하면 된다. 설정은 setcap, getcap 명령을 사용한다.
capabilities 맨페이지를 보면, CAP_NET_BIND_SERVICE이 1024이하 포트(privileged ports)에 대해 권한 부여 역할을 한다.
CAP_NET_BIND_SERVICE Bind a socket to Internet domain privileged ports (port numbers less than 1024). |
1) capabilities 설정을 위해 libcap2가 패키지가 필요하다.
① 데비안/우분투는 libcap2-bin 패키지(setcap, getcap 등의 명령을 갖고 있음)를 설치한다.
② CentOS는 http://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/ 에서 소스를 받는다.
이 소스 컴파일을 위해서는 libattr-devel 패키지가 설치되어 있어야 한다.
2) setcap명령으로 CAP_NET_BIND_SERVICE를 1024이하 포트를 사용할 파일명에 설정을 해주면 된다. 심볼릭 링크 파일은 지정할 수가 없다.
3) 설정을 확인하려면 getcap을, 그리고 설정을 다시 빼려면 -r 옵션을 사용하면 된다.
[ 명령 형식 ] setcap capability1[,capability2][=-+][value] <filename> # setcap 'cap_net_bind_service=+ep' /usr/bin/nc (테스트를 위해 nc명령을 사용했다.) # getcap /usr/bin/nc /usr/bin/nc = cap_net_bind_service+ep # # setcap -r /usr/bin/nc (설정 빼기) # getcap /usr/bin/nc # |
capabilities 이름인 cap_net_bind_service은 대소문자 구별이 없지만, set 해당하는 ep는 소문자만 사용해야 한다.
연산자는 +, -, = 3가지로, chmod의 연산자와 동일한 의미를 갖는다. 각각 추가(+), 삭제(-), 지정한 권한으로 동일(=)하게 변경한다.
file capabilities set에는 다음 3가지가 있다.
- e : effective -> 효력부여
- p : Permitted -> 허용
- i : Inheritable -> exec 할 때 권한 상속 여부
capabilities manpage에서 각 set에 대한 자세한 설명있다. 파일에 cap_net_bind_service 권한을 부여하려면 ep 또는 eip를 셋팅하면 된다는 것만 알고 있으면 된다.
다음은 999포트를 오픈한 예이다. 일반 유저로 실행된 것을 확인할 수 있다.
[ 일반 유저가 999포트 바인딩 ] $ nc -l 999 (데비안 또는 우분투에서는 nc -l -p 999) [ root로 확인 ] # netstat -anp Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:999 0.0.0.0:* LISTEN 18021/nc <--- 999포트를 18021 PID가 ... 생략 ... # ps auxww|grep "[n]c " coffeenix 18021 0.0 0.0 1728 612 pts/15 S+ 18:59 0:00 nc -l 999 <--- 18021 PID 실행유저는 coffeenix |
libjli.so 오류가 발생 시
1. etc/ld.so.conf.d/java.conf 파일에 libjli.so 파일의 절대 경로를 입력 (단 파일이 위치하고 있는 상위 디렉토리까지만, 예를 들어 jdk설치경로/lib/amd64/jli)
2. /sbin/ldconfig 실행
조치후 구동하면 된다.
4. Linux에서 capabilities 좀 더 알기
1) PAM 모듈
pam_cap.so PAM 모듈도 제공하므로, 로긴을 하거나 su 이용시 '유저별'로 다른 권한을 부여할 수 있다. /etc/security/capability.conf 에 capabilities를 설정한다.
CentOS에서 libcap2 소스를 가져다 PAM 모듈을 설치할 경우 먼저 pam-devel 패키지가 설치되어 있어야 한다.
2) 프로세스의 capabilities set 상태 확인
capabilities의 Effective/Inheritable/Permitted set(집합)은 각각 32bit로 이뤄져 있다. 그리고, 각 bit별로 어떤 권한(자격)을 갖는지 지정되어 있다. CAP_NET_BIND_SERVICE 은 11번째 bit(0100 0000 0000 => hex 0400)에 해당한다. 나머지 권한들이 몇 번째 bit인지는 /usr/include/linux/capability.h에 자세히 나와있으니 생략한다.
프로세스의 capabilities set 상태 확인해보자. setcap으로 설정해둔 프로그램을 실행한다. 그리고 해당 프로세스의 PID를 확인한다. cat /proc/<pid style="font-family: 돋움체, 굴림, seoul, arial, verdana; line-height: normal;">/status|grep Cap 명령으로 bitmap 결과를 확인할 수 있다.
</pid>
# cat /proc/26494/status|grep cap CapInh: 0000000000000000 <-- Inheritable capabilities CapPrm: 0000000000000400 <-- Effective capabilities (Hex 0400. 즉, CAP_NET_BIND_SERVICE이 set되었음을 확인할수 있다.) CapEff: 0000000000000400 <-- Permitted capabilities (Hex 0400) CapBnd: ffffffffffffffff |
<pid style="font-family: 돋움체, 굴림, seoul, arial, verdana; line-height: normal;">
5. Solaris에서 RBAC로 권한 부여
전통적인 유닉스 시스템에서는 root가 모든 권한을 갖는다. 그러나 이 root의 권한 일부를 다른 유저에게 할당하는 것이 쉽지 않았다.
RBAC(Role Based Access Control, 롤 기반 접근 제어)는 root가 갖는 권한 중 일부를 묶은 후, 그 권한 묶음을 유저에게 부여할 수가 있는 보안모델이다. 권한의 묶음을 '롤(Role)'이라는 부른다.
① 롤을 생성(roleadd)하고, (roleadd)
② 그 롤이 어떤 권한을 갖는 롤인지를 정의를 한다. (roleadd, rolemod)
③ 그리고, 그 롤에 속하는 유저를 설정하면 된다. (usermod)
이런 롤 기반 접근 제어는 업무 역할별로 권한 묶음을 만들어 유저에게 권한을 분산할 수가 있다. 예를 들어, 파일시스템 mount를 할 수 있는 권한을 'disk'라는 롤명(롤명은 ID처럼 임의로 만들면 됨)으로 만들었다고 하자. 그리고 이 롤에 유저를 할당하면 해당 유저는 mount 권한을 부여받게 된다.
자세한 권한 목록은 privileges man page 또는 /etc/security/priv_names에서 확인할 수 있다.
다음은 coffeenix유저가 1024이하 포트를 열수 있는 권한(권한명 : PRIV_NET_PRIVADDR)을 갖는 예이다. 롤 생성 방법으로 시도해봤지만 쉽게 되지 않아서, 롤 생성없이 유저에게 직접 권한을 부여하는 방법으로 처리를 했다. 설정 후 재로긴하면 권한을 갖는다.
</pid>
# usermod -K defaultpriv=basic,net_privaddr coffeenix |
<pid style="font-family: 돋움체, 굴림, seoul, arial, verdana; line-height: normal;">
/etc/user_attr에서 다음을 확인할 수 있다.
</pid>
coffeenix::::type=normal;defaultpriv=basic,net_privaddr |
<pid style="font-family: 돋움체, 굴림, seoul, arial, verdana; line-height: normal;">
6. 참고자료
* FreeBSD Handbook - 16.10 The MAC portacl Module
http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/mac-portacl.html
* Is there a way for non-root processes to bind to “privileged” ports (<1024) on Linux?
http://stackoverflow.com/questions/413807/is-there-a-way-for-non-root-processes-to-bind-to-privileged-ports-1024-on-linux
* Linux : capabilities man page
http://www.kernel.org/doc/man-pages/online/pages/man7/capabilities.7.html
* Linux : setcap man page
http://manpages.ubuntu.com/manpages/lucid/man8/setcap.8.html
* Linux Security Capabilities
http://fpmurphy.blogspot.com/2009/05/linux-security-capabilities.html
* [Linux] POSIX capability (한글)
http://studyfoss.egloos.com/5338802
* Solaris 10 Non-Root User...Port 80
http://blogs.sun.com/tls/entry/solaris_10_non_root_user
* Custom Roles Using RBAC in the Solaris OS
http://www.sun.com/bigadmin/content/submitted/custom_roles_rbac.jsp</pid>
'IT > UNIX' 카테고리의 다른 글
MAC OS - catalina에서 JAVA 6 설치하지 (0) | 2019.11.07 |
---|---|
CentOS 7 Minimal 설치 및 초기 설정 (0) | 2019.08.26 |
서버간 파일공유 하기 (nfs) (0) | 2019.08.23 |
GCP CentOS7 디스크 추가 하기 (0) | 2019.07.23 |
unix bash For Loop 예제 (0) | 2019.02.27 |