뭘 이런걸..

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
Posted
Filed under Tech/프로그래밍
VIM 에서 PHP를 작성할 때, indent 기능을 사용할 경우 switch가 아래와 같이 정렬이 됩니다. 

<?php 
switch ($a) {
case '1' :
echo "1\n";
break;
default :
echo "12\n";
}
?>


즉, case 문의 depth가 switch와 동일하게 되는 현상인데, 이걸 싫어 하는 사람도 많습니다. 그래서 case를 indent 시키고 싶다면 .vimrc 에 다음의 설정을 추가해 주세요.

let g:PHP_vintage_case_default_indent = 1


그리고 다시 indent 시켜 보면 다음과 같이 정렬이 됩니다.

<?php
switch ($a) {
case '1' :
echo "1\n";
break;
default :
echo "2\n";
}
?>


2016/07/08 17:50 2016/07/08 17:50
Posted
Filed under security
자 5월 말에 Chrome browser가 51로 업그레이드 되면서 NPN 기능을 제거 했습니다.

NPN 기능이 대표적으로 사용되는 것은 SPDY와 HTTP2 protocol 입니다. SPDY는 NPN 기반으로 동작을 하고, HTTP2는 ALPN 기능을 이용하여 동작을 하는데, NPN 기반에서도 동작이 가능 합니다.

그럼, Browser에서 NPN 기능을 제거한 것이 무엇이 문제냐는 점인데.. Browser에서 NPN 기능을 제거를 하면 서버에서도 ALPN 기반으로만 HTTP2 서비스가 가능하며 서버가 NPN 기반일 경우에는 불가능 합니다. 또한, 기존의 SPDY는 chrome에서는 불가능 하다는 의미입니다.

즉, Chrome browser는 서버에서 ALPN을 지원하지 않으면, 아무리 서버에서 spdy나 http2 protocol을 지원하도록 해도 HTTP/1 로 통신을 해 버리게 되는 것입니다.

뭐, 다 좋습니다. NPN이 사장된 기능이고, 사장된 기능은 빨리 제거를 하는 것이 좋을 테니까요.

그럼 무엇이 문제일까요?

현재 ALPN은 openssl 1.0.2 부터 지원을 합니다. 1.0 은 NPN을 하고요. 문제는 이 openssl 버전에 있습니다.

openssl은 대부분의 OS 배포본에서 core 패키지로 분류가 됩니다. 즉, openssl을 함부로 업그레이드 했다가는 시스템 동작이 원할하지 못하게 된다는 것을 의미합니다. 일단 ssh 연결이 불가능 하게될 가능성이 가장 큽니다. 즉, openssl 은 함부로 업그레이드가 불가능한 패키지로 봐야 하기 때문에, 상위 버전의 openssl을 사용하려면 별도의 위치에 openssl을 설치한, 별도 위치의 openssl library를 link를 해야 합니다. 문제는 이 부분이 누구나 쉽게 할 수 있는 부분이 아니라는 것이죠.

또한, openssl은 심각한 보안버그가 자주 나오는 편인데, 별도로 관리되지 않는 openssl을 설치해서 사용한다는 것도 보안 운영상 아주 취약한 문제이고요.

현재 리눅스 우리나라에서 서버로 많이 사용되는 배포본과 openssl library 버전은 다음과 같습니다.

Operating System OpenSSL Version ALPN and NPN Support
CentOS/Oracle Linux/RHEL 5.10+ 0.9.8e Neither
CentOS/Oracle Linux/RHEL 6.5+, 7.0+ 1.0.1e NPN
Ubuntu 12.04 LTS 1.0.1 NPN
Ubuntu 14.04 LTS 1.0.1f NPN
Ubuntu 16.04 LTS 1.0.2g ALPN and NPN
안녕 리눅스 2 1.0.1e NPN
안녕 리눅스 3 1.0.1e NPN + ALPN (back porting)

일단 안녕 리눅스는 많이 사용되는 배포본은 아니지만, 제가 배포하는 거라 살짝 끼워 넣었습니다.

위의 상황을 보시면 바로 아실 수 있을 겁니다. 현재 운영되는 대부분의 배포본들이 ALPN을 지원하지 않는다는 의미입니다. 즉, 브라우저에서 NPN 기능을 제거해 버리면 대부분의 spdy나 http2 기능을 제공하던 시스템들이 무력화가 되는 것이나 마찬가지라는 것입니다.

NPN 기능이 activeX 처럼 악의 축도 아니고, 상황이 바쳐주지 않은 상태에서 이렇게 NPN을 제거해 버림으로서 일단 SPDY 서비스는 완전히 무력화가 되어 버렸습니다.

가장 많이 사용하는 브라우저인 Chrome이 과감하게 NPN을 제거함으로서 이제 OS 배포본 업체들의 행보가 궁금해 집니다. 운영되고 있는 대부분의 배포본에서 제공하는 openssl 1.0.0, 1.0.1 버전에 ALPN 기능을 back porting을 해 줄 것인지 아니면, 고객들 보고 알아서 하라고 할 것인지.. 재미있는 상황이 되어 버렸습니다.


일단, 구글의 조치로 인하여, 구글을 제외한 http2 환경은 지랄 맞는 상황이 되어 버렸습니다. :-)


P.S.
안녕 리눅스 3은 http2의 지원을 위해서 openssl 1.0.2의 ALPN을 back porting을 해 놓았으며, 안녕 리눅스 2도 현재 back porting을 진행 하고 있습니다.

2016/06/24 01:04 2016/06/24 01:04
김정균

안녕 리눅스 2에서 openssl-1.0.1e-48.an2.1 부터 ALPN patch 가 적용이 되었습니다. 적용이 되지 않은 시스템들은 다음 명령으로 업데이트 하세요.

yum update "openssl*"

Posted
Filed under 주절주절
얼마전 NHN에서 나눔 고딕 코딩 후속으로 D2 coding 이라는 코딩용 font를 공개했습니다. (나눔 고딕 코딩도 그렇고 참 감사히 잘 쓰고 있습니다. ^^)

본인은 보통 가변폭 폰트보다 고정폭 폰트를 선호하는 경향이 있어, 이렇게 고정폭 폰트가 나오면 참 감사히 사용합니다.

하지만, 출시된지 얼마되지 않아서인지, D2 coding의 웹폰트가 아직은 없더군요.

그래서 제가 사용하려고 만든 D2 coding webfont를 공유 합니다.

http://cdn.kldp.org/fonts/D2-Coding/D2Coding-Webfont.tar.xz

에서 받으실 수 있습니다. 누가 jsdelivr에 올려 주실 수 있으면 올려 주세요.

형식은, eot, woff, woff2, ttf 형식으로 지원합니다.

압축은 xz 압축으로, tar 명령으로는 "xvfpJ' 옵션으로 해제 가능 하며, 윈도우즈에서는 7-zip 같이 xz 압축 지원하는 압축도구에서 해제 가능 합니다.
2016/04/08 15:26 2016/04/08 15:26
한태승

D2Coding 웹폰트는 네이버 개발자 페이지에 건의해도 진행되지 않던 부분인데,
공유해주셔서 감사합니다. 덕분에 유용하게 이용하겠습니다.

김정균

d2coding 웹폰트 다운로드 위치가 https://github.com/Joungkyun/font-d2coding/releases 로 변경이 되었습니다.

jsdelivr에 올리려고 하는데 등록이 되지를 않네요. 왜 등록이 안되는지는 모르겠음. pull request 주소는 다음과 같습니다. 혹시 이유 아시는 분 도와주세요 :-0

https://github.com/jsdelivr/jsdelivr/pull/13355

김정균

8/21에 full request 요청을 했는데 11/30에 merge가 되었네요. 3달 10일 걸렸습니다. :-)

http://www.jsdelivr.com/projects/font-d2coding

jsdelivr 에 있는 1.2 는 공식 1.2 버전이 아니라, 1.1 버전에서 css 수정 사항이 반영된 것입니다. 공식 1.2 버전은 금일 full request를 올렸고 1.2.1로 배포가 될 예정입니다.

공식 버전과 웹폰트간의 변경 사항이 틀려서 웹폰트 버전을 3자리로 하여, 두번째 자리 까지는 공식 버전을 따라가고, 웹폰트의 변경 사항은 마지막 자리에서 할 예정입니다.

Posted
Filed under Tech/Tip & Trick
Note: OS X 10.11 El Capitan에서의 방법이 업데이트 되었습니다.

아.. Mac Lion에서 동작하는 Apple Script를 찾느라 힘이 들어 공유 합니다. (일단 한글 자료가 없어서..)

일단, finder > 응용 프로그램 > Apple Script 편집기를 실행 해서 다음의 코드를 넣습니다.

주의할 것은, Apple Script를 사용하기 위해서는 "시스템 설정" > "손쉬운 사용" 의 하단에 "보조 장비에 대한 접근 활성화"가 체크되어 있어야 합니다.

Safari Private Browsing 한국어 모드



OS X 10.11 El Capitan 에서는 다음과 같이.. (https://discussions.apple.com/message/29223652#29223652 참조)

Safari Private Browsing 한국어 모드



영문판은 다음과 같이 하셔야 합니다.

Safari Private Browsing 영문 모드

2016/01/20 18:26 2016/01/20 18:26
Posted
Filed under Tech/프로그래밍
안녕 리눅스 3의 PHP 버전을 7로 올려서 release 하려고 하다보니.. 별 개삽질을 다하고 있다.
일단, PHP wiki에서 https://wiki.php.net/phpng-upgrading 를 참고하여 작업을 하면 되는데, 문제는 여기에 나와있지 않은 경우가 너무나 많다.

결국에는 PHP 소스 코드를 뒤져서 구현해야 하는.. 더군다나 여기에 나와있지 않은 hole들도 굉장히 많다. 대표적으로..

char * input;
int ilen;
int no;
 
if ( zend_parse_parameters (ZEND_NUM_ARGS(), "sl", &input, &ilen, &no) == FAILURE )
    RETURN_FALSE;
이 코드는 컴파일을 잘 되나, 그냥 segfault 가 발생한다. s(String)과 l(integer)는 다음과 같이 해 줘야 한다.

zend_string * Zinput = NULL;
zend_long no;

char * input;
int ilen;

if ( zend_parse_parameters (ZEND_NUM_ARGS(), "Sl", &input, &no) == FAILURE )
    RETURN_FALSE;

input = ZSTR_VAL (input);
ilen = ZSTR_LEN (input);
zend_parse_parameters 에서 string은 zend_string으로 변경해 줘야 하고, long은 zend_long로 선언을 변경해 줘야 한다. 이 외에도, string을 zval 변수로 변환하는 경우도 짜증난 케이스

zval *zv;
MAKE_STD_ZVAL (zv)
ZVAL_STRING (zv, "문자열");
이 코드는 다음과 같이 변경 되어야 한다.
zval zv;
ZVAL_STRING (&zv, "문자열");
,,,
zval_ptr_dtor (&zv);
이 외에도 너무 많아서 정리가 힘들다. PHP7은 잘못하면 python 3 꼴이 날지도 모르겠다. 3party module 중에서 PHP 7을 지원을 얼마나 빨리 해 주ㄴ냐가 관건인 듯.. 물론 php code 호환 문제 까지는 바라보기도 전에 말이다. (갈 길이 너무 멀다....) 내가 만든 3party 확장들은 PHP 7 지원을 위한 코드 변경이 너무 많아서, 아예 PHP 7 지원하는 버전은 하위 호환성을 포기하고 컴파일을 막아 버렸다. --;
#if PHP_API_VERSION < 20151012
#error "************ PHP version dependency problems *******************"
#error "This package requires over php 7.0.0 !!"
#error "If you build with php under 7.0.0, use mod_krisp 2.x version"
#error "You can download mod_krisp 2.x at http://mirror.oops.org/pub/oops/libkrisp/APIs/php/"
#endif
참고로.. mod_korean migraion diff 를 보면.. 얼마나 많이 변경을 해야 하는지 대충 감이 올 듯.. 이 링크는 아직도 작업이 완료되지 않은 상태이다. --;
2015/12/29 05:15 2015/12/29 05:15
김정균

ncurses extension 작업 완료

ncurses: https://bugs.php.net/bug.php?id=71299

김정균

하.. 숨어있는 문제들이 훨씬 더 많군요 :-(

내부 구조의 많은 변경으로, 단순하게 API 변경만 따라가다가는 엉뚱한 문제들이 송송 터지네요. 예를 들면 https://github.com/expressif/pecl-event-libevent/issues/3 요런 문제들이..

PHP 7의 걸림돌은 3rd party extension 들이겠군요.

참고로 PHP 7을 지원하도록 수정된(거의 비공식적인) 3rd party extension 목록을 공유합니다.

memcache: https://github.com/websupport-sk/pecl-memcache/tree/php7
libevent: https://github.com/expressif/pecl-event-libevent/
event: https://bitbucket.org/osmanov/pecl-event/src/7f233a23b34bb100753971766c5ea2611fe8d023/?at=php7-dev
mongodb: http://pecl.php.net/package/mongodb/1.1.1

등등..