뭘 이런걸..

Posted
Filed under Tech/프로그래밍
LePuTTY의 ZMODEM 기능을 iPuTTY에 포팅을 했습니다.

일단, 동작은 잘 하는 것 같네요. 좀 더 사용해 보고 문제가 없으면 0.69.1 로 릴리즈 할 예정 입니다. 그전에 PuTTY 0.70이 나오면 0.70으로 릴리즈 될 것이고요 :-)

https://github.com/iPuTTY/iPuTTY/pull/25

참고 하세요.
2017/06/12 03:40 2017/06/12 03:40
Posted
Filed under Tech/프로그래밍
어쩌다 보니 iPuTTY maintaing을 하게 되었습니다. 기존 관리자였던 김준기님이 작년에 project를 더이상 하지 않겠다고 project site에 공지를 올렸고, 비공식적으로 PuTTY 업데이트를 반영해서 사용하다가 그냥 제가 맡아서 하기로 하였습니다.

어쩌다 보니, 뒷처리 담당자로서 우뚝선 느낌입니다. :-)

어쨌든 4/29에 릴리즈된 PuTTY 0.69의 대응 버전을 릴리즈 했으며, 추가적으로 기능을 좀 더 강화 했습니다. 솔직히 GUI programing이 처음이고 PuTTY 코드를 제대로 본 것도 아니라서 잘 유지할 수 있을지 모르겠지만, 나서는 사람이 없어 일단 제가 총대를 매게 되었습니다. (아쉬운 사람이 해야 하는 관계로 T.T)

project 사이트는 bitbucket에서 GitHub로 이전을 했으며, https://github.com/iPuTTY/iPuTTY/wiki 를 이용하면 되겠습니다.

0.69 에서 제공하는 기능은 다음과 같습니다.

  • 한글 UI 제공
    • 다시 한글 UI를 제공 하며, pagent, puttygen, pscp, psftp 등 모든 프로그램에서 한글 UI를 제공 합니다.
  • 이제 64bit binary를 제공 합니다.
  • psftp 와 pscp 에서 UTF-8을 사용할 수 있습니다.
  • 한글 입력 모드에서 Esc를 누르면 자동으로 영문 입력 모드로 변경이 됩니다.
  • 서버 호스트키 체크 여부 옵션이 추가 되었습니다.
  • Cygterm backend 가 추가 되었습니다.
  • psftp 에서 ls 명령으로 개별 file 목록을 볼 수 없는 버그를 수정했습니다.

자세한 사항은 https://github.com/iPuTTY/iPuTTY/wiki 를 참고 하세요.
2017/05/17 01:34 2017/05/17 01:34
Posted
Filed under Tech/Tip & Trick
방금전, openvpn-gui 의 한글 번역이 review 를 통과 했습니다. 대충 번역만 해서 pull request를 날렸더니 까다롭게 하나하나 짚어 내는 군요.

그래서 좀 신경써서 테스트도 해 보고 해서 다시 제출을 하니 방금 approve가 되었습니다.

아마 다음 버전 릴리즈시에는 openvpn-gui 에서 한글을 보실 수 있을 겁니다. (단, 번역 품질은 ㅎㅎ)

https://github.com/OpenVPN/openvpn-gui/pull/155

사용자 삽입 이미지
사용자 삽입 이미지
2017/04/26 00:30 2017/04/26 00:30
Posted
Filed under Tech/Tip & Trick
금일 Xen Server 7.1로 업그레이드를 한 이 후에, oops.org VM 이 아래의 메시지를 뿌리면서 load가 되지 않는 문제가 있었습니다.

Failed Starting VM 'oops.org'

This operation cannot be performed because the specified virtual disk could not be found

정말 당황 스러웠습니다. 검색을 해 봐도 뾰족한 수는 없고, VM host에 로그인 해서 LVM partition을 봐도 제대로 인식은 되어 있었고..

oops.org는 기존에 Xen Server 7.0으로 운영을 하고 있었으며, Disk는 LVM으로 다음과 같이 사용을 하고 있었습니다.

Pysical disk:
  • /dev/sda   SSD 150G
  • /dev/sdb   SATA 500G

Logical disk:
  • oops.org
  • an2.pkg.oops.org
  • an2.x86.pkg.oops.org
  • test.oops.org

그런데, 다른 VM은 모두 load가 되는데, 하필 oops.org VM만 load가 되지 않는 것이었습니다. 특정 가상 disk를 인식을 할 수 없다는데, VM host에서 아무리 확인을 해 봐도 oops.org partition은 살아 있고, 실제로 다른 VM에 attach를 해서 확인을 해 봐도 잘 살아 있더군요.

2017년 1월 경에 장비 fault 나면서 복구 한지 이제 2달 정도 지났고, 정신 없이 지내다 보니 백업도 2017년 1월달 까지 밖에 없고, 좀 난감하더군요. 그래서 어쩔 수 없이 있는 파티션 날릴 각오를 하고 최후의 꽁수를 진행해 보았습니다.

  1. Detach oops.org virtual disk
  2. oops.org VM 제거
  3. oops.org VM 재생성
  4. Reattach oops.org virtual disk
  5. VM 재생성시에 생성된 가상 disk 제거
  6. boot 옵션을 Hard Disk로만 되도록 설정 변경
  7. rebooting

이 작업 이 후에, 다시 인식을 하여 oops.org VM load를 성공했습니다.

살짝 암담했었는데, 겨우 복구하고 한숨 한번 쉬어 주고, 이 글을 작성 합니다. --;
2017/03/29 04:24 2017/03/29 04:24
Posted
Filed under Tech/안녕리눅스
안녕 리눅스 2.x 의 RPM-GPG-KEY 변경 공지 입니다.

혹시 YUM으로 /etc/yum.repos.d/AnNyung.repo 에 등록되어 있는 패키지 업데이트가 되지 않은 경우에는, 다음 사항을 참고 하여 조치를 하십시오.

  1. 대상

    안녕 리눅스 2 x86_64, i686

  2. 증상

    /etc/yum.repos.d/AnNyung.repo 에 등록된 repository의 패키지 업데이트가 되지 않는 증상이 발생할 수 있음

  3. 원인

    2017.01.16 OOPS.org 서버 이전 중 서버 노후화에 의한 HDD, memory 손상. 특히 HDD 파손으로 인하여 RAID 10이 깨져서 데이터 복구 불가능하여, 안녕 리눅스 2의 패키지 빌드 private key를 손실 하여, 새로운 키를 생성해서 모든 패키지를 resign 함.

  4. 해결책

    업데이트가 되지 않을 경우에는, 수동으로 annyung-release package 업데이트를 해야 함. 기존의 패키지들을 신규 생성한 private key로 다시 sign 을 하였기 때문에 예전의 공개키로는 verify 를 할 수 없습니다. 그러므로 공개키를 갱신시키기 위하여, 공개키를 포함하고 있는 annyung-release package를 수동으로 재설치 해 주어야 합니다.

    [root@host ~]$ rpm -Uhv --force http://mirror.oops.org/pub/AnNyung/2/inst/annyung-release.rpm


    깨끗이 정리를 위해서는 분실된 이전 공개키를 제거해 주십시오.

    [root@host ~]$ rpm -e gpg-pubkey-0eff2026-4eedfee5

OOPS.org 서버는 Xen server 6.5에 4개의 VM (oops.org, an1.pkg.oops.org, an2.pkg.oops.org, an2.x86.pkg.oops.org)으로 구성이 되어 있습니다. 이번 사건은 RAID를 너무 맹신했던 것이 가장 큰 문제였으며, 2번째로는 장비의 노후화 및 서버 부품 조달 비용에 대한 문제가 있었습니다.

RAID 복구 시에 깨끗하지 못한 여분 하드를 사용한 것이 RAID가 깨진 가장 큰 원인이었으며, 여분 하드 역시 다른 RAID 정보를 가지고 있어 발생한 문제 입니다. 더군다나 RAID 10을 맹신하여, VM 2대에 key가 분산이 되어 있어 외부 백업을 하지 않은 것이 가장 큰 원인 입니다.


2017/01/22 20:11 2017/01/22 20:11
Posted
Filed under Tech/안녕리눅스
2016년 12월 31일 24:00 에 윤초가 추가될 예정입니다. (UTC 기준이니 우리나라 기준으로는 2017년 1월 1일 9시가 8시 59분 60초가 되겠네요.)

윤초에 대해서는 2012년에 요란을 떨 정도로 큰 장애(LinkedIn, Reddit  등의 Java로 운영을 하는 시스템들의 장애)가 있었습니다.

가장 마지막 윤초는 2015년 6월 30일에 있었으며, 2012년 사건 이후로 OS level과 time server들이 잘 대응을 해서 별 문제 없이 넘어간 듯 싶습니다.

그리고, 2016년 12월 31일에 또 윤초가 추가되게 됩니다.

여기서 논할 것은, 2012년의 문제가 잘 해결이 되어 있더라도, 또 다른 버그로 인하여 이 문제가 발생하는 것을 원천적으로 제거하는 방법에 대해서 논합니다. 물론 이론적인 것들은 인터넷 상에서 잘 논한것들이 있으니 여기서 다루지는 않습니다. 여기서는 이 이론들을 실무에 어떻게 적용을 하느냐 입니다.

윤초에 영향을 받는 서비스가 없거나 윤초 따윈 안중에 없어.. 하시는 분들은 사뿐이 브라우져를 즈려 밟으시고 무시하시면 되겠습니다.

2012년 사태 이후로, Google에서 1초를 그냥 확 추가하는 것이 아니라 대략 20여시간에 걸쳐서 1초를 추가하는 Leap Smear 를 적용한 public NTP를 제공 합니다.

이 글에서는 Leaf Smear를 NTP와 chrony에 어떻게 적용을 해서 운영을 할 수 있는지에 대하여 기술 합니다.

일단, 별도로 Time server를 운영하지 않는다면, Goolge Public NTP를 사용하는 것을 고려하십시오. (물론 난 윤초랑 관련이 없어 하시는 분들은 그냥 사뿐이 무시 하시면 됩니다.)

제가 ubuntu machine의 경우에는 다양한 버전이 없어서, CentOS/RHEL 을 기준으로 설명 합니다.

  1. CentOS / RHEL 4 or 5
    CetnOS 5 이하처럼 EOL이 종료된 배포본의 경우에는 문제를 해결할 수 있는 방법은 Goolge Public NTP 처럼 leap smear를 제공하는 time server를 이용하여 시간 동기화를 하는 방법 밖에는 없습니다.
    .
  2. time server에 시간 동기화를 하지 않는 경우
    time 동기화를 하지 않는 경우에는, tzdata package를 최신으로 갱신해 주어야 합니다. yum을 이용하여 tzdata 를 최신 상태로 업데이트를 하는 것으로 해결이 됩니다.
    .
  3. ntp 또는 chrony를 이용하여 외부 time 서버에 동기화 하는 방법
    1. Goolge Public NTP로 동기화 대상을 변경
    2. 또는 leap smear를 제공하는 time server로 동기화 대상 변경.
    3. 또는 아래의 방법(4,5번)을 이용하여 ntpd 또는 chrony로 time server를 구성하여 동기화.
    4. 또는 각 서버에 4,5번의 설정을 반영
      .
  4. ntpd를 이용하여 time server 운영 시
    ntpd를 구동할 때 command line option으로 -x 옵션을 주어 구동을 합니다. RHEL 6.6 이하의 ntp에서는 ***-x*** 옵션이 정상적으로 동작하지 않는 버그가 있습니다. NTP를 최신으로 업데이트 해 주십시오.
    [root@host ~]$ yum update ntp
    [root@host ~]$ service ntpd stop
    [root@host ~]$ ntptime -s 0 -f 0
    [root@host ~]$ # ntpd의 OPTIONS 변수에 -x 를 추가해 줍니다.
    [root@host ~]$ cat /etc/sysconfig/ntpd
    # Drop root to id 'ntp:ntp' by default.
    OPTIONS="-x -u ntp:ntp -p /var/run/ntpd.pid -g"
    [root@host ~]$ service ntpd restart
  5. chronyd를 이용하여 time server 운영 시
    chorny를 최신 버전으로 업데이트 합니다. 다음 옵션은 chrony >= 2.0 의 조건에서 사용이 가능 합니다. RHEL 7.0 에는 chrony 1.3이 포함이 되어 있습니다. yum 으로 chrony를 최신으로 업데이트 해 주십시오. 업데이트 이후, 다음의 설정을 chrony.conf에 추가 한 다음, chrony를 재시작 합니다.
    # slew mode for leap second
    leapsecmode slew
    maxslewrate 1000
    smoothtime 400 0.001 leaponly

Reference:
  1. https://srad.jp/~marusa/journal/608570/
  2. https://srad.jp/~marusa/journal/593599/
  3. http://www.criticalworld.co.kr/?p=281
2016/12/28 23:41 2016/12/28 23:41
Posted
Filed under Tech/안녕리눅스
협업 프로젝트시에 여려명이서 코드를 같이 생성하다 보면 각자의 코딩 스타일 때문에 코드가 난장판이 되는 문제가 있습니다. 이 문제 때문에 대부분의 프로젝트들은 각각의 코딩 규칙을 생성하여 사용 합니다.

여기서는 이 난장 중에서 tab과 space가 섞여서 있는 경우에 대한 체크를 위한 팁을 작성해 봅니다. 특히 이 경우는 Pythonindent에서 가장 큰 특징으로 나타납니다.

일단, 구분을 하기 위해서는 vim의 syntax 를 이용합니다. python 파일을 예로 들겠습니다.

먼저, python에 적용될 syntax 파일을 생성합니다.

[oops@an3 ~]$ # vim syntax directory를 생성 합니다.
[oops@an3 ~]$ mkdir -p ~/.vim/syntax
[oops@an3 ~]$ # tab의 바탕색을 푸른색으로 하는 syntax color를 설정 합니다.
[oops@an3 ~]$ cat <<EOF > ~/.vim/syntax/python.vim
syn match Tab "\t"
hi def Tab guifg=blue ctermbg=blue
EOF
[oops@an3 ~]$

위와 같이 작업을 한 후에, python file을 vim으로 열면 tab이 푸른색 바탕으로 보이게 됩니다. space와 tab이 섞여 있을 경우 쉽게 구분이 되어지게 됩니다.

여기까지는 인터넷에서 검색만 잘하면 찾을 수 있는 내용입니다. 그럼 이 글을 포스팅 하는 이유는 다음과 같습니다.

제가 사용하다 보니, 일단 언어마다 syntax 파일을 생성해 줘야 하는 불편함과, 항상 이렇게 보고 싶지 않다는 점 입니다. 즉, 필요할 때만 구분을 하고 싶은데, 위의 팁은 vim 설정 파일을 변경하면서 사용을 해야 한다는 것이죠. 그래서 이 불편함들을 해결하기 위하여, 이 기능을 vim function으로 만들고 특정 키에 bind 해서 사용하도록 합니다. (물론 안녕 리눅스의 VIM package에 포함될 기능 입니다.)

여기서 부터의 내용은, 위의 내용을 싹 잊어 버리시면 됩니다. (일단 위의 내용을 적용했다면, 싹 원복 하라는 의미입니다.) 일단, AnNyung LInux VIM plugin project site에서 TabDistinct plugin을 다운로드 받습니다.

[oops@an3 ~]$ curl -o tabdistinct.vim \
https://raw.githubusercontent.com/AnNyung/VIM_plugins/master/TabDistinct/tabdistinct.vim
[oops@an3 ~]$

다운로드 받은 tabdistinct.vim 을 root 권한이 있을 경우에는 $VIM/vimfiles/plugin 디렉토리에 저장을 하고, root권한이 없을 경우에는 ~/.vim/plugin 에 저장을 합니다. 아래의 예는 일반 계정의 예 입니다.

[oops@an3 ~]$ # vim plugin directory를 생성 합니다.
[oops@an3 ~]$ mkdir -p ~/.vim/plugin
[oops@an3 ~]$ mv tabdistinct.vim ~/.vim/plugin/
[oops@an3 ~]$

이 작업을 마친 후에, 아무 파일이나 열어서 command mode에서 언더바(_)키('shift' + '-')를 누르시면 of/off toggle이 가능해 집니다.


자세한 사항은 https://github.com/AnNyung/VIM_plugins/tree/master/TabDistinct 를 참고 하세요
2016/12/23 21:26 2016/12/23 21:26
Posted
Filed under Tech/안녕리눅스
이번에는 PHP 성능을 높일 수 있는 방법 2가지에 대해서 기술해 봅니다. 아래의 내용은 안녕 리눅스의 PHP package를 빌드할 때 성능을 높이기 위하여 한 작업을 기술 하는 것입니다.

먼저 PHP VM type을 변경하여 성능을 높이는 방법에 대해서 알아 보겠습니다.

PHP 5 까지 configure 옵션에 보면 --with-zend-vm 이라는 옵션이 있습니다. (7.0 부터는 없어졌습니다.) configure --help를 해 보면 아래 와 같이 설명이 나옵니다.

Zend: 
--with-zend-vm=TYPE Set virtual machine dispatch method. Type is
one of "CALL", "SWITCH" or "GOTO" TYPE=CALL


즉, zend vm type에는 "CALL", "SWITCH", "GOTO" 모드가 있고, 기본값은 "CALL" 이라는 내용입니다. 그리고 이 옵션으로 zend vm type을 변경할 수 있다고 되어 있습니다.

하지만, 실제로 configure 시에 이 옵션은 동작하지 않습니다. 그래서 7.0 부터는 제거가 되었습니다.
configure 얘기를 한 이유는, 검색을 하다 보면, 이 옵션을 이용하여 VM type을 변경할 수 있다는 글들이 나오기 때문입니다. configure 옵션으로는 VM type 변경이 되지 않기 때문에 언급을 한 것입니다. 7.0 부터 제거가 되었다는 것은 configure 옵션이 실제 동작을 하지 않기 때문에 제거가 되었다는 의미이지 7.0에서는 여기서 설명하는 것이 적용이 안된다는 의미가 아닙니다. 7.0 이후에서도 동일하게 성능을 높일 수 있습니다.

그럼, zend vm type이 뭔지, 그리고 어떻게 하면 변경할 수 있는지에 대해서 설명을 합니다. (빌드 후에 변경은 불가하고, 빌드 시에 선택을 해야 합니다.)

일단, zend vm에 대한 기본 내용은

https://github.com/php/php-src/blob/master/Zend/README.ZEND_VM

에서 확인하실 수 있습니다. 간략하게 설명을 하면, opcode optimize 방법이라고 보시면 됩니다. (설명 파일에는 executor 방법이라고 나오는데, 표현하기 쉽게 최적화라고 했습니다.) 일단 성능은 다음과 같습니다.

GOTO > SWITCH > CALL

일단,  GOTO를 기준으로 하면, php source code 안에 있는 bench.php를 기준으로 CALL보다 20% 정도의 성능 향상이 이루어 집니다.

그러면 왜 기본값이 GOTO가 아니라 가장 성능이 안 좋은 CALL이냐.. 에 대한 건 저도 아직 제대로 된 설명을 못 찾았습니다. (어쩌면 영어 자료만 있어서 그럴 수도 있습니다. ^^;)

다만, 빌드시에 GOTO의 경우에는 memory가 아주 많이 필요하며, 빌드 시간이 CALL로 빌드하는 것 보다 3~4배 정도가 더 걸립니다. build machine 성능에 따라 차이가 더 커질수도 있습니다. (특정 아키텍쳐나 compiler에 따라 case by case로 발생 합니다.) RHEL 5의 i686 시스템에서 php 5.2를 GOTO로 빌드 할 때 memory가 12G 정도를 잡아 먹어서, mameory가 모잘라  swap을 늘려서 빌드 했던 적도 있습니다. 이건 case by case이기 때문에 꼭 나타나는 증상이라고 할 수는 없지만 CALL로 빌드할 때 보다는 많은 메모리가 필요 합니다.

일단, 빌드 방법은 다음과 같습니다. ./configure를 실행하기 전에 php-src/Zend 디렉토리에서 다음의 명령을 실행합니다.

[root@an3 php-7.1.0]$ cd Zend
[root@an3 Zend]$ php zend_vm_gen.php --with-vm-kind=GOTO
[root@an3 Zend]$ cd ..
[root@an3 php-7.1.0]$ ./configure --with-옵션....
[root@an3 php-7.1.0]$ make -j 8 && make install
 

이 명령을 실행하면, zend_vm_execute.h 와 zend_vm_opcodes.h 파일이 새로 생성이 됩니다.

참고:
5.6 에서는 GOTO로 이 파일들을 생성하면, 빌드시에 syntax error가 발생하는 버그가 있습니다. 5.6에서는 zend_vm_execute.h에서 "constant_fetch_end"이 duplicate되었다는 에러가 발생 합니다. zend_vm_execute.h에서 중복된 constant_fetch_end 라벨을 constant_fetch_end1, constant_fetch_end2, constant_fetch_end3 과 같이 중복되지 않게 변경해 주면 됩니다.
zend_vm_gen.php 스크립트를 이용하여 zend_vm_execute.h 와 zend_vm_opcodes.h 파일을 GOTO type을 새로 생성한 후에, 기존의 configure; make; make install 을 이용하여 설치를 진행하면 됩니다.

안녕 리눅스 1/2/3 에 들어있는 PHP는 모두 GOTO 모드로 빌드 되어 있고, 네오위즈에서 사용하는 PHP와 TMON에서 사용하는 PHP도 모두 GOTO로 빌드되어 동작하고 있습니다. 실제 상용 시스템에서 사용하여 검증은 되었으니, 직접 빌드해서 사용하는 분들은 빌드시에 적용을 해 보시면 좋을 겁니다.

OS 선택을 고려해야 하고 CentOS 6/7 을 생각하고 계신 분들이라면 안녕 리눅스를 선택하는 것을 고려해 보심이 ^^; CentOS 6/7 호환이라 전환을 한다고 해서 특별하게 달라질 것은 없습니다.

다음은 realpath_cache_force 기능에 대해서 기술 합니다.

이 기능에 대해서는 안녕 리눅스 3 사용자 가이드의 PHP 문서의 4.7 realpath_cache_force 항목에서 자세히 설명을 하고 있습니다.

위의 링크의 내용을 간략히 말하자면, PHP 파일에서 realpath_cache 라는 기능이 있습니다. 이 기능은 PHP가 파일 시스템에 접근을 할 때에 mtime(modify time) 을 체크하여 일정 시간동안 caching을 하여 성능을 높이는 것인데, link()와 symlink() function으로 race condition을 이용해서 open_basedir 을 무력화 시킬 수 있는 보안 버그가 발견이 되어, PHP 개발자들이 open_basedir을 사용할 경우에는 realpath_cache를 사용하지 못하도록 코드를 변경해 버렸습니다. 그래서 open_basedir을 사용할 경우에 접속이 많은 사이트의 경우에는 30% 정도의 성능이 감소되는 문제가 있습니다. (이것 역시 case by case로 접속이 많은 수록 성능의 차이가 많이 나게 됩니다.)

안녕 리눅스 2.0 부터는 realpath_cache_force 라는 옵션을 추가하여, open_basedir을 사용하더라도, 이 옵션이 활성화가 되어 있으면, realpath_cache를 할 수 있도록 해 주며, 문제가 되는 link()와 symlink() 함수들을 사용하지 못하게 하여 문제를 해결하고 성능을 높일 수 있도록 합니다.

이 기능은 TMON에서 주유권 이벤트시에 접속이 너무 몰려서 최적화 작업을 하면서 만든 기능으로 안녕 리눅스 2.0의 PHP에 반영이 되었습니다.

CentOS 6 또는 7 사용자들의 경우에는 CentOS를 안녕 리눅스로 전환을 시키면 이 기능을 사용할 수 있습니다. (물론 PHP 버전이 다르므로 약간의 migration은 필요할 수 있습니다.)


안녕 리눅스 전환을 얘기를 하면 강요같이 받아들이는 분들도 계셔서 안녕 리눅스에 반영된 patch file을 아래에 공유 합니다. 다음은 안녕 리눅스 3의 php 7.1.0에 적용된 패치 파일 입니다. (copy & paste 이기 때문에 tab이 space로 변환이 되어 copy & paste로는 patch가 적용이 안되니 어디를 수정하는지 부분만 참고를 하세요.)

diff -urNp php-7.1.0.org/ext/standard/link.c php-7.1.0/ext/standard/link.c
--- php-7.1.0.org/ext/standard/link.c 2016-12-02 11:07:40.000000000 +0900
+++ php-7.1.0/ext/standard/link.c 2016-12-09 17:28:34.301410867 +0900
@@ -126,6 +126,16 @@ PHP_FUNCTION(symlink)
char dirname[MAXPATHLEN];
size_t len;

+ if (PG(open_basedir) && *PG(open_basedir) && PG(realpath_cache_force)) {
+ php_error_docref(
+ NULL TSRMLS_CC,
+ E_ERROR,
+ "The relapath_cache_force option is enabled. "
+ "For security issue, symlink function is not usable."
+ );
+ RETURN_FALSE;
+ }
+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "pp", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) {
return;
}
@@ -182,6 +192,16 @@ PHP_FUNCTION(link)
char source_p[MAXPATHLEN];
char dest_p[MAXPATHLEN];

+ if (PG(open_basedir) && *PG(open_basedir) && PG(realpath_cache_force)) {
+ php_error_docref(
+ NULL TSRMLS_CC,
+ E_ERROR,
+ "The relapath_cache_force option is enabled. "
+ "For security issue, link function is not usable."
+ );
+ RETURN_FALSE;
+ }
+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "pp", &topath, &topath_len, &frompath, &frompath_len) == FAILURE) {
return;
}
diff -urNp php-7.1.0.org/main/main.c php-7.1.0/main/main.c
--- php-7.1.0.org/main/main.c 2016-12-09 17:28:25.502936720 +0900
+++ php-7.1.0/main/main.c 2016-12-09 17:28:34.302410921 +0900
@@ -725,6 +725,7 @@ PHP_INI_BEGIN()

STD_PHP_INI_ENTRY("realpath_cache_size", "16K", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_size_limit, virtual_cwd_globals, cwd_globals)
STD_PHP_INI_ENTRY("realpath_cache_ttl", "120", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_ttl, virtual_cwd_globals, cwd_globals)
+ STD_PHP_INI_ENTRY("realpath_cache_force", "0", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_force, php_core_globals, core_globals)

STD_PHP_INI_BOOLEAN("upload_image_check", "0", PHP_INI_SYSTEM, OnUpdateBool, upload_image_check, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("upload_image_check_log", "0", PHP_INI_ALL, OnUpdateBool, upload_image_check_log, php_core_globals, core_globals)
@@ -1779,7 +1780,7 @@ int php_request_startup(void)
}

/* Disable realpath cache if an open_basedir is set */
- if (PG(open_basedir) && *PG(open_basedir)) {
+ if (PG(open_basedir) && *PG(open_basedir) && !PG(realpath_cache_force)) {
CWDG(realpath_cache_size_limit) = 0;
}

@@ -2362,7 +2363,7 @@ int php_module_startup(sapi_module_struc
zend_register_standard_ini_entries();

/* Disable realpath cache if an open_basedir is set */
- if (PG(open_basedir) && *PG(open_basedir)) {
+ if (PG(open_basedir) && *PG(open_basedir) && !PG(realpath_cache_force)) {
CWDG(realpath_cache_size_limit) = 0;
}

diff -urNp php-7.1.0.org/main/php_globals.h php-7.1.0/main/php_globals.h
--- php-7.1.0.org/main/php_globals.h 2016-12-09 17:28:25.503936774 +0900
+++ php-7.1.0/main/php_globals.h 2016-12-09 17:28:34.303410975 +0900
@@ -154,6 +154,7 @@ struct _php_core_globals {
zend_long max_input_nesting_level;
zend_long max_input_vars;
zend_bool in_user_include;
+ zend_bool realpath_cache_force;

zend_bool upload_image_check;
zend_bool upload_image_check_log;
diff -urNp php-7.1.0.org/php.ini-development php-7.1.0/php.ini-development
--- php-7.1.0.org/php.ini-development 2016-12-09 17:22:39.522475756 +0900
+++ php-7.1.0/php.ini-development 2016-12-09 17:28:34.304411028 +0900
@@ -351,6 +351,12 @@ disable_classes =
; http://php.net/realpath-cache-ttl
;realpath_cache_ttl = 120

+; If set on safe_mode or open_basedir, realpth_cache is disable. Set 1 this
+; directive, realpath_cache is enable with realpath_cache_size and realpath_cache_ttl
+; although safe_mode or open_basedir set enable. If you want to enable this variable,
+; We recommand that symlink function is set to disable_functions
+;realpath_cache_force = 0
+
; Enables or disables the circular reference collector.
; http://php.net/zend.enable-gc
zend.enable_gc = On
diff -urNp php-7.1.0.org/php.ini-production php-7.1.0/php.ini-production
--- php-7.1.0.org/php.ini-production 2016-12-09 17:22:39.523475809 +0900
+++ php-7.1.0/php.ini-production 2016-12-09 17:28:34.305411082 +0900
@@ -351,6 +351,12 @@ disable_classes =
; http://php.net/realpath-cache-ttl
;realpath_cache_ttl = 120

+; If set on safe_mode or open_basedir, realpth_cache is disable. Set 1 this
+; directive, realpath_cache is enable with realpath_cache_size and realpath_cache_ttl
+; although safe_mode or open_basedir set enable. If you want to enable this variable,
+; We recommand that symlink function is set to disable_functions
+;realpath_cache_force = 0
+
; Enables or disables the circular reference collector.
; http://php.net/zend.enable-gc
zend.enable_gc = On
2016/12/14 02:29 2016/12/14 02:29
Posted
Filed under Tech/프로그래밍
요즘 IT 업계에서 보안이 화두이기는 한 것 같습니다. 지인에게서 ISMS 인증이 빡세어 졌다는 등의 소식도 있고..

근래 free lancer로 일을 하면서 진행하는 project에서도 역시 보안이 화두인가 봅니다. project 마무리를 하고 있는 상황에서, 갑자기 설정 파일을 암호화를 해 달라는 요청을 받았습니다. 그것도 다른 파일들은 나두고 설정 파일만..

대충 복호화가 가능한 알고리즘을 이용해서 eval로 실행을 시킬까 고민을 잠시 하기는 했었는데, 영 eval 은 아닌 것 같고 검색을 해 보니 php_screw 라는 것이 보이더군요. 그래서 이 놈을 사용하려고 code를 좀 살펴 보았는데, 좀 걸리는 부분들이 많더군요.

  1. php_unscrew로 복호화가 가능하다.
  2. decode api (zencode.c) 에서 전역 변수를 사용하여 thread safe 하지 못하다. (프로젝트와는 상관이 없지만...)
  3. 복호시에 temp file을 생성한다.
  4. decode 시에 memory realloc을 너무 자주 한다. 사이즈가 큰 암호화 파일의 경우 성능을 떨어뜨릴 수 있다.
  5. 파일 몇 개를 암호화 하기 위해서, 모든 파일의 magic key 체크를 한다.

등등.. 복호화 문제와 성능의 문제가 고민이 되었습니다.

성능의 문제의 경우, 처음 php_screw를 살펴 보던 시점에서는 opcode cache를 고려하지 않았고 또한 테스트를 해 보지 않은지라 성능상의 문제가 좀 커 보였었던 점이 있습니다. 지금 시점에서 말하자면, opcacheAPC와 같은 PHP code cache 프로그램을 이용하면, magic key 체크, decode 등의 이슈는 상당히 많이 줄어들게 됩니다.

다만, 하고 있는 프로젝트가 순간 폭주가 가능한 서비스인지라, cache time이 짧을 경우 문제가 될 소지가 있었고, 또한 php_uncrew에 의한 복호화의 문제도 있어 어쩔수 없이 코드를 건드리게 되었고, mod_screwim (PHP Screw Improved)라는 fork 버전을 릴리즈 했습니다.

대략적인 개선 사항은, 다음과 같습니다.

  1. temp flie을 생성하는 방식에서 신성욱님의 개선사항을 반영하여 PHP memstream을 이용한 방식으로 개선
    1. 개선 사항에 있던 memory leak 수정
    2. 반환값이 없을 경우 segfault 발생하는 문제 수정
    3. 파일을 2번 open 하는 버그 수정
  2. 전역 변수를 없애 thread safe하도록 수정
  3. memory reallocation 로직을 수정하여 사이즈가 큰 암호화된 파일을 decode 시에 성능 개선
  4. 암호화 SEED key 자동 random 생성
  5. screwim.enable ini 옵션이 enable 상태에서만 decodeing을 한다. (ini_set 이용 가능하며, magic key 검사 이슈)
  6. runtime encrypt/decrypt API 제공 (screwim_encrypt(), screwim_decrypt(), screwim_seed())
  7. php_unscrew 방식의 복호화를 어렵게 수정

뭐, 그 외에도 자잘한 것들이 있기는 하지만 그리 중요한 것 같지는 않고, 자세한 사항은 https://github.com/OOPS-ORG-PHP/mod_screwim/ 을 참고 하시기 바랍니다.

그리고, 이 모듈(mod_screwim)을 사용하려면 (또는 php_screw를 사용하려면) 꼭 (opcache 또는 APC 같은..) cache를 같이 사용해야 decode 시의 성능 손실을 최소화 할 수 있습니다.
2016/11/30 01:36 2016/11/30 01:36