글쓴이 보관물: totoli78

Pydio 2G초과하는 대용량 업로드 설정방법

Pydio(구 AjaXplorer) 2G초과하는 대용량 업로드 설정에 있어 해야할 방법을 적으려고한다.
1. PHP 설정

php.ini 파일에서 수정할 것들

 

max_execution_time =120

max_input_time = 60

memory_limit =256M

post_max_size =2G

upload_max_filesize =2G

default_socket_timeout = 60

필자는 최대 6GB 까지 업로드 하려고 하기 때문에 다음과 같이 수정하고 아파치를 재시작하였다.

(각 설정별의 내용을 이해하고 있다면 다르게 해도 괜찮다. 이건 필자의 개인설정이다.)

max_execution_time = 0

max_input_time = -1 

memory_limit =512M

post_max_size =5G

upload_max_filesize =5G

default_socket_timeout = 1800

max_execution_time (무제한 : 0) 

– 최대 실행시간

파일용량이 커지면 그만큼 시간이 길어져야 하지만 적절한 시간을 모르므로 제한을 해제했다.

max_input_time (무제한 : -1)

– php 엔진이 데이터를 업로드 받는 시간

파일용량이 커지면 그만큼 시간이 길어져야 하지만 적절한 시간을 모르므로 제한을 해제했다.

memory_limit

– 파일 용량이 커지면 그만큼 메모리의 용량도 늘어야 한다고 한다.

post_max_size

– Post 방식으로 전송될 최대 데이터 크기

upload_max_filesize

– 업로드할 파일 최대크기 (필자의 서버는 5G가 한계)

default_socket_timeout

 

– 연결시간 유지 (초단위이고 적당히 30분 잡아주었다.)

2. Pydio 설정

여기까지  php.ini 만 수정하면 문제없이 될 것같지만 사실 Pydio 내부에서도 수정이 필요하다.

안그러면 파일업로드 제한에 걸리거나 목록에서 업로드한 파일의 용량이 제대로 표시되지 않거나 v파일이 불완전하게 업로드되는 현상이 발생한다.

 

2.1. 목록에서 파일용량 제대로 표시하기

관리자 아이디로 pydio에 로그인 한 후

“설정 – Application Parameters – Feature plugins – Workspaces Drivers – File System(Stendard) ” 에서

REAL SIZE PROBING 의 설정을 Yes로 바꾸어준후 오른족 상단에 저장버튼클릭

 

2.2 Jumploader 설치 및 활성화

Jumploader를 공식 사이트에 가서 최신버전을 받는다. 필자는 2.27.0 버전을 사용했다.

Jumploader – http://jumploader.com/download.html

다운받은 “jumploader_z.jar” 를 “public_html\plugins\uploader.jumploader” 안에 압축 풀지않고 그대로 넣어둔다.

“설정 – Application Parameters – Feature plugins – Uploaders -java(Big Files)”에서

Install Applet 버튼을 눌러서 설치, 그담에 ENABLED을 Yes로 바꾼 다음 오른족 상단에 저장버튼클릭

그리고 Standard / Remote Server / PLUploader 는 꺼주면 끝.

설치가 다 올바르게되면 업로드 버튼 누를 시에 아래와 같은 창으로 바뀐다.

[참고] 만약 Uploder에서 아무런 리스트가 나타나지 않는다면?

필자에게 발생한 것이고 임시방편으로 찾은 방법을 적어둔다.

서버에서 “public_html\plugins” 에 접근하여 “uploader.flex”의 폴더명을 바꾼다.

uploader.flex → _uploader.flex

“설정 – Application Parameters – Feature plugins” 에서 Refresh plugins cache 를 클릭

“설정 – Application Parameters – Feature plugins – Uploaders” 에 옆에 있는 새로고침 버튼 클릭하면 나온다.

필요한 설정을 다 하고 나면 “_uploader.flex”의 폴더명을 원래대로 바꾸고

_uploader.flex → uploader.flex

“설정 – Application Parameters – Feature plugins” 에서 Refresh plugins cache 를 클릭하면 끝.

flex플러그인이 없으면 업로드를 했는데 업로드가 안되는 현상이 발생하므로 한번 용량작은 파일로 테스트 해봐야한다.

* 포럼을 뒤지고 구글링을 해도 무슨 이유인지는 밝히지를 못했다. 아는이 있으면 덧글로 좀 알려줘요.

[참고] 끝마치기 전에 개인적인 생각

보통 대용량파일은

목록에서 제대로 용량이 표시가 안되고 다운로드가 안되는게 문제지 업로드가 문제인건 아니므로

그냥 “2.1 목록에서 파일용량 제대로표시하기” 까지만 진행한 다음에 업로드는 FTP로 해서 따로 올리는 것이 낫다고 생각한다. 파일을 업로드할 경로는 다음과 같다.

Default Files – “public_html\data\files”

My Files – “public_html\data\personal”

Windows WIFI-AP 목록과 KEY 추출

## backup profile
netsh wlan export profile key=clear folder=C:\wifi_profiles (폴더 없으면 C:\ 에다가)

## restore profile
netsh wlan add profile filename=”c:\wifi_profiles\totoli_AP.xml” user=all (백업된 프로파일 하나씩 복원)

[Docker] docker-compose 를 이용해 ELK 구축하기 ( + mySql, Nori)

1. ELK ?

Elasticsearch, Logstash, Kibana 오픈 소스 프로젝트 3개를 합쳐서 ELK 라고 한다. Elasticsearch 는 검색 및 분석 엔진으로 무료버전으로도 기본적인 기능은 충분히 사용가능하다. Logstash는 여러 소스에서 동시에 데이터를 수집하여 변환한 후 Elasticsearch 와 같은 곳에 ‘stash’로 전송하는 서버 사이드 데이터 처리 파이프라인을 말한다. Kibana 는 사용자가 Elasticsearch 를 시각화하여 사용할수 있는 툴이다.

여기서는 이미 사용하고 있는 docker 기반 mySql 을 Elasticsearch 에 logstash 를 이용해 동기화 하고, 검색하는 부분만 포스팅할 예정이다.

 

2. Nori ?

한글 검색을 올바르게 수행하기 위해서는 형태소 분석기 plug-in 을 Elasticsearch 에 따로 설치해주어야 하는데, 다른 다양한 형태소 분석기들도 많지만 필자는 Elasticsearch 공식문서를 보면서 작업하기 수월하기 위해 Nori 형태소 분석기를 사용하기로 하였다. nori는 elasticsearch 가 실행된 상태에서 해당 bash 에 접속해 설치하면 된다.

$ docker exec -it elasticsearch /bin/bash 
$ bin/elasticsearch-plugin install analysis-nori #elasticsearch container 에서 명령

nori를 이용한 검색을 해야하는 데이터 컬럼에 대해서는 반드시 mapping analyzer 셋팅을 해주어야 한다. 예를들어 ‘name’이라는 column 에 형태소 분석을 이용한 한글검색이 가능하게 하고자 한다면 mapping 은 다음과 같은 형태일 수 있다.

 "name": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          },
          "analyzer":"nori_analyzer"
        }

 

3. docker-compose

version: '3.2'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.6.1 #기본 이미지 사용
    container_name: elasticsearch
    environment:
      ES_JAVA_OPTS: "-Xmx256m -Xms256m"
      discovery.type: single-node #간단한 local 테스트를 위해 single-node로 구성
    volumes:
      - /usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elk
  logstash:
    container_name: logstash
    image: docker.elastic.co/logstash/logstash:7.6.1
    environment:
      LS_JAVA_OPTS: "-Xmx256m -Xms256m"
    volumes:
      - type: bind
        source: ./config/logstash/config/logstash.yml
        target: /usr/share/logstash/config/logstash.yml
        read_only: true
      - type: bind
        source: ./config/logstash/pipeline
        target: /usr/share/logstash/pipeline
        read_only: true
      - ./jar/mysql-connector-java-8.0.18.jar:/usr/share/logstash/logstash-core/lib/jars/mysql-connector-java-8.0.18.jar #mysql 사용을 위한 jdbc-connector 다운
    networks:
      - elk
    depends_on:
      - elasticsearch #elasticsearch 가 실행된 이후 logstash 실행되도록 depends_on 설정
  kibana:
    container_name: kibana
    image: docker.elastic.co/kibana/kibana:7.6.1
    ports:
      - 5601:5601
    networks:
      - elk
    depends_on:
      - elasticsearch #elasticsearch 가 실행된 이후 kibana 실행되도록 depends_on 설정
    
networks:
 elk:
  external:
    name: mysql-network #이미 사용하고 있는 db와 연결을 위해 mysql-docker network 와 연결이 되도록 external 설정을 따로 해주었다. 

volumes:
 elasticsearch: #volume container 사용
    

 

이미 떠있는 mysql container 와의 연결을 위해 external network 설정을 따로 해주었으나, 만약 elk 구축과 함께 database 를 실행한다면 external 연결은 해줄필요가 없다. 기본적인 ELK 설정을 거이 따르고 있으며 여기서는 mysql 연결을 위한 부분과 single-node 사용하는 부분만 수정하였다.

4. mysql 과 동기화 작업 설정

동기화 하고 싶은 데이터가 있다면 logstash.conf 파일에서 설정해주면 된다. 여기서는 crontab 과 수정일을 이용하여 마지막 데이터를 동기화해 가지고 오도록 작업하였다.

input {
  jdbc {
    jdbc_driver_library => "/usr/share/logstash/logstash-core/lib/jars/mysql-connector-java-8.0.18.jar"
    jdbc_driver_class => "com.mysql.jdbc.Driver"
    jdbc_connection_string => "jdbc:mysql://[mysql-container-name]:[mysql-container-host]/allpal?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Seoul&autoReconnect=true"
    jdbc_user => "[mysql-id]"
    jdbc_password => "[mysql-password]"

    columns_charset => {
      "[한글데이터를 가지고 있는 column 명]" => "UTF-8"
    }

    statement => "SELECT *, UNIX_TIMESTAMP(modification_time) as unix_ts_in_secs FROM [table name] WHERE 
    (UNIX_TIMESTAMP(modification_time) > :sql_last_value AND modification_time < NOW())"

    jdbc_paging_enabled => true
    use_column_value => true
    tracking_column => "unix_ts_in_secs"
    tracking_column_type => "numeric"
    clean_run => true
    schedule => "*/5 * * * * *"  # crontab 표기법의 스케쥴 설정
  }
}

output {
  elasticsearch {
    hosts => "elasticsearch:9200"
    index => "[index명]"
    document_id => "%{_id}"
  }
  stdout {
    codec => rubydebug
  }
}

[대괄호]안에 있는 부분들은 해당 상황에 맞게 입력하면 되는 값이며, 여기서는 위에서 언급한것처럼 modification_time 이라는 수정일 컬럼을 이용하여 동기화하였다. 새로 추가되거나, 수정/삭제 된 경우에도 데이터가 자동으로 동기화 되기 위해서 다음과 같이 작업을 진행하였다.

 

각 환경에 맞게 수정한 docker-compose.yml 파일과 logstash.conf 등 설정파일들 준비가 완료되었다면 docker-compose.yml 파일이 있는 디렉토리에서 docker-compose up 을 통해 해당 파일이 실행되는것을 확인할 수 있으며, localhost:5601 에 접속하여 kibana 에서 편하게 실제 index가 들어간 모습과, mapping 등을 확인할 수 있다.

To hide removable drives from file explorer in left tree view

To hide removable drives from the Navigation Pane in Windows 10, follow the instructions below.

  1. Open Registry Editor.
  2. Go to the following Registry key:
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\DelegateFolders\{F5FB2C77-0E2F-4A16-A381-3E560C68BC83}

    Tip: See How to jump to the desired Registry key with one click.

  3. Rename the subkey {F5FB2C77-0E2F-4A16-A381-3E560C68BC83} by adding a hyphen ‘-‘ before it so its new name is -{F5FB2C77-0E2F-4A16-A381-3E560C68BC83}. See the following screenshot:windows 10 hide remobable drives navigation pane
  4. If you are running 64-bit Windows 10, repeat the step above here:
    HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\DelegateFolders
  5. Close all Explorer windows for the change to take effect.

That’s it.
Before:

before
After:

after
To restore removable drives in the navigation pane, rename the mentioned subkey from -{F5FB2C77-0E2F-4A16-A381-3E560C68BC83} back to {F5FB2C77-0E2F-4A16-A381-3E560C68BC83}.

You can save your time and use Winaero Tweaker to hide or show Removable Drives in the navigation pane.

Docker – Oracle 12c 설치

Oralce 12C를 설치할 디렉토리 생성 및 권한 변경

 mkdir vm_ora12c

chmod -R a+w vm_ora12c

Oracle 12c 이미지 조회

docker search oracle

[docker_test@blue ~]$ docker search oracle

INDEX       NAME                                          DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED

docker.io   docker.io/oraclelinux                         Official Docker builds of Oracle Linux.         515       [OK]

docker.io   docker.io/sath89/oracle-12c                   Oracle Standard Edition 12c Release 1 with…   409                  [OK]

docker.io   docker.io/frolvlad/alpine-oraclejdk8          The smallest Docker image with OracleJDK 8…   343                  [OK]

docker.io   docker.io/alexeiled/docker-oracle-xe-11g      This is a working (hopefully) Oracle XE 11…   273                  [OK]

docker.io   docker.io/sath89/oracle-xe-11g                Oracle xe 11g with database files mount su…   224                  [OK]

docker.io   docker.io/wnameless/oracle-xe-11g             Dockerfile of Oracle Database Express Edit…   115                  [OK]

docker.io   docker.io/jaspeen/oracle-11g                  Docker image for Oracle 11g database            77                   [OK]

docker.io   docker.io/isuper/java-oracle                  This repository contains all java releases…   55                   [OK]

docker.io   docker.io/oracle/openjdk                      Docker images containing OpenJDK Oracle Linux   49                   [OK]

docker.io   docker.io/airdock/oracle-jdk                  Docker Image for Oracle Java SDK (8 and 7)…   39                   [OK]

docker.io   docker.io/sath89/oracle-ee-11g                Dockerfile of Oracle Database Enterprise E…   34                   [OK]

docker.io   docker.io/cogniteev/oracle-java               Oracle JDK 6, 7, 8, and 9 based on Ubuntu …   24                   [OK]

docker.io   docker.io/ingensi/oracle-jdk                  Official Oracle JDK installed on centos.        21                   [OK]

docker.io   docker.io/oracle/nosql                        Oracle NoSQL on a Docker Image with Oracle…   17                   [OK]

docker.io   docker.io/n3ziniuka5/ubuntu-oracle-jdk        Ubuntu with Oracle JDK. Check tags for ver…   16                   [OK]

docker.io   docker.io/sgrio/java-oracle                   Docker images of Java 7/8/9/10 provided by…   16                   [OK]

docker.io   docker.io/andreptb/oracle-java                Debian Jessie based image with Oracle JDK …   7                    [OK]

docker.io   docker.io/flurdy/oracle-java7                 Base image containing Oracle’s Java 7 JDK       5                    [OK]

docker.io   docker.io/davidcaste/debian-oracle-java       Oracle Java 8 (and 7) over Debian Jessie        4                    [OK]

docker.io   docker.io/martinseeler/oracle-server-jre      Oracle’s Java 8 as 61 MB Docker container.      4                    [OK]

docker.io   docker.io/teradatalabs/centos6-java8-oracle   Docker image of CentOS 6 with Oracle JDK 8…   4

docker.io   docker.io/publicisworldwide/oracle-core       This is the core image based on Oracle Lin…   1                    [OK]

docker.io   docker.io/bitnami/oraclelinux-extras          Oracle Linux base images                        0                    [OK]

docker.io   docker.io/pivotaldata/oracle7-test            Oracle Enterprise Linux (OEL) image for GP…   0

docker.io   docker.io/softwareplant/oracle                oracle db                                       0                    [OK]

Oracle docker image download

docker pull sath89/oracle-12c

[docker_test@blue ~]$ docker pull sath89/oracle-12c

Using default tag: latest

Trying to pull repository docker.io/sath89/oracle-12c …

latest: Pulling from docker.io/sath89/oracle-12c

863735b9fd15: Pull complete

4fbaa2f403df: Pull complete

44be94a95984: Pull complete

a3ed95caeb02: Pull complete

b8bc6e8767ee: Pull complete

c918da326197: Pull complete

448e1619a038: Pull complete

faadd00cf98e: Downloading [====>                                              ] 266.9 MB/2.768 GB

fab7f453b7c6: Download complete

c98ac63d2108: Download complete

download 된 image 확인

[docker_test@blue ~]$ docker images

REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE

docker.io/sath89/oracle-12c   latest              ee3351d51185        2 months ago        5.7 GB

실행

docker run –name oracle12c -d -p (외부포트):8080 -p (외부포트):1521 -v (외부경로):/u01/app/oracle sath89/oracle-12c

[docker_test@blue ~]$ docker run –name oracle12c -d -p 28080:8080 -p 21521:1521 -v /home/docker_test/vm_ora12c:/u01/app/oracle sath89/oracle-12c

185cb33e3b92b6473c13f35e687b960d42da9e547ceb600e5a181d0ed7fca631

실행 로그 확인

 docker logs -f oracle12c

[docker_test@blue ~]$ docker logs -f oracle12c

Database not initialized. Initializing database.

Starting tnslsnr

Copying database files

1% complete

3% complete

11% complete

18% complete

26% complete

37% complete

Creating and starting Oracle instance

40% complete

45% complete

……

ls: cannot access /docker-entrypoint-initdb.d/*: No such file or directory

Import finished

Database ready to use. Enjoy! 😉

oracle 의 사용자 계정 생성

docker exec  -it oracle12c /bin/bash

su oracle

export PATH=$PATH:$ORACLE_HOME/bin

sqlplus /as sysdba

create user testuser identified by oracle;

grant dba to testuser;

exit (연속)

[docker_test@blue ~]$ docker exec -it oracle12c /bin/bash

root@185cb33e3b92:/# su oracle

oracle@185cb33e3b92:/$ export PATH=$PATH:$ORACLE_HOME/bin

oracle@185cb33e3b92:/$ sqlplus / as sysdba

SQL*Plus: Release 12.1.0.2.0 Production on Mon Oct 29 05:24:43 2018

Copyright (c) 1982, 2014, Oracle.  All rights reserved.

Connected to:

Oracle Database 12c Standard Edition Release 12.1.0.2.0 – 64bit Production

SQL> create user testuser identified by oracle

2  /

User created.

SQL> grant dba to testuser

2  /

Grant succeeded.

해당 유저로 접속 확인

 docker exec -it oracle12c sqlplus testuser/oracle

[docker_test@blue ~]$ docker exec -it oracle12c sqlplus testuser/oracle

SQL*Plus: Release 12.1.0.2.0 Production on Mon Oct 29 05:26:30 2018

Copyright (c) 1982, 2014, Oracle.  All rights reserved.

Connected to:

Oracle Database 12c Standard Edition Release 12.1.0.2.0 – 64bit Production

SQL>

 

헐리우드랙 익스프레스! 가벼운 무게에 무거운 성능!

차량은 SUV에 장착하였고 해당 헐리우드랙 익스프레스 모델은

승용차와 SUV에 상관없이 장착가능합니다.

장착전 차량 트렁크 부분의 홈부분을 확인해주시고

스포일러가 플라스틱을 제작되어있는 차량은 먼저 스포일러가 흔들리는지 케리어 선에 간섭을

주는지 확인하시는것을 추천드립니다.

케리어의 상단과 하단부분은 갈고리로 되어있으며 트렁크 상단과 하단에 체결됩니다.

하단부분의 경우 간혹 차량에 마무리상태에 따라 갈고리가 걸릴수 없는 구조로 되어있는 모델이 있으며

이때에는 차량에 철골부분이 장착될만한 곳이 있는 차량이 설치가능합니다.

차량에 접촉하는 부분은 두꺼운 스폰지 재질로 되어있어 차량 손상을 최소화 합니다.

사용중 스폰지재질이 손상되면 압박붕대나 부드러운 재질의 커버로 미연에 감아주시는것이 좋습니다.

SUV 차량에 장착한 모습입니다.

차량에 중심부쪽을 설치해주시면 됩니다.

차량에 닿는 부분은 두군데이며

SUV차량은 트렁크 하단 부분만 닿게되며 상단부분은 유리창에 장착하게됩니다.

상단에 장착된 모습과 기본적으로 자전거 거치부분은 약간 상향되게 장착하시는것이 좋습니다.

자전거 거치부분은 플라스틱으로 되어있어 상단부분은 강한 고무스트랩으로 되어있습니다.

거치대의 조절은 안쪽의 둥근 플라스틱을 돌려서 위치조정을 하게됩니다.

거치대의 끈조절부위는 철재로 되어있어 체결강도와 안전성은 걱정안하셔도 됩니다!!

고무스트랩은 충분한 강도를 가지고 있으며 길이조절이 가능하여 탑튜브 두께에 따라 조절하시면 됩니다

두대가 장착가능한 부분이며 자전거 거치하는 부분은 앞뒤로 위치 조절이 가능합니다.

거치부분의 여분의 끈이 정리되는 부분이 없는것이 아쉽지만 일반 고무줄로 간단하게 해결하실수있습니다.

고정되는 스트랩부분은 손으로 누르지않는 이상 절대 풀리지 않습니다.

한대장착된 모습입니다.

탑튜브 위에 고무스트랩으로 고정을 해주시고 뒷부분도 사진처럼 고정시켜주시면 됩니다.

위 사진처럼 느슨하게 장차하시면 자전거가 고정되지않고 이동합니다.

두대 장착한 모습입니다.

자전거를 좌우로 겹치게 장착하면 간섭없이 거치하실수있습니다.

캐리어의 중앙부에는 하나의 여분의 끈이 장착되어있으며

용도는 자전거를 캐리어와 고정하기위한 끈입니다.

두대를 장착후 고정끈으로 고정한 모습입니다.

두대 장착한 모습.

두대 장착모습.

튼튼하게 고정된 캐리어 모습!!!!

간단한 장착과 가벼운 가격…

 

헐리우드랙 익스프레스!!!

이 글은 info 카테고리에 분류되었고 태그가 있으며 님에 의해 에 작성되었습니다.

SYSMON + ELK STACK을 이용하여 간단한 EDR 만들기

개요

현재 Microsofts에서 제공하는 도구 모음인 Sysinternalsuite에는 Sysmon이라는 도구가 있다. Sysmon은 윈도우 운영체제에서 높은 수준의 모니터링을 제공한다. 백그라운드에서 실행되며 모니터링 결과를 이벤트 로그에 기록한다. 이러한 유용한 기능을 제공하는 Sysmon은 많이 알려져 있으나 그 결과가 이벤트 로그에 저장되기 때문에 실시간으로 결과값을 보는 것이 기존 SIEM이나 다른 장비에 연동하기 어렵다면 모니터링이 불편하였다. 하지만, 오픈소스인 ELK Stack의 다양한 기능을 이용한다면 이점을 커버할 수 있다.

이번 포스팅에서는 Sysmon에 대하여 알아보고 생성블로그관리된 로그를 ELK Stack을 통해 모니터링 하는 방법에 대하여 알아보고자 한다.

Sysmon 설치

우선적으로 이번 프로젝트에 중심이 될 Sysmon을 설치한다. https://docs.microsoft.com/en-us/sysinternals/downloads/sysmon에 설치한다.

다운 받은 Sysmon을 압축 해제하고 Command 창을 이용하여 설치한다. Sysmon 설치와 관련한 옵션은 “-h” 옵션을 통해 자세히 확인할 수 있다.

[그림 1] Sysmon64.exe -h

 

Sysmon을 더 유용하게 사용하기 위해서는 config 파일을 이용하여야 한다. 직접 설정하는 방법도 있으나 이미 github를 이용해 공개된 Sysmon config파일을 이용하는 방법을 추천한다. 부족한 부분은 제외하고 추가할 부분을 추가하여 설정이 가능하다.

설정 파일은 공개된 github(https://github.com/SwiftOnSecurity/sysmon-config)에서 다운로드 하였다.

설치 명령은 다음과 같다.

Sysmon64.exe -accepteula -i C:\Users\Administrator\Desktop\Sysmon\sysmonconfig-export.xml -l -n

[그림 2] Sysmon 설치

최초 설치에는 “-I” 옵션을 사용했으나 이후 설정파일에 변경이 있다면 “-c” 옵션으로 변경된 옵션을 적용할 수 있다.

설치가 끝나면 자동으로 Sysmon이 작동이 되는데 비스타 이후 버전은 Applications and Services Logs/Microsoft/Windows/Sysmon/Operational 경로에 Sysmon로그가 쌓이며 이전 버전은 System event 로그에 쌓이게 된다. 윈도우에서 기본으로 제공하는 이벤트 뷰어로 확인이 가능하다.

[그림 3] EventLog

Sysmon의 이벤트 로그는 다음과 같이 저장되며 의미를 가진다.

Event ID 설명
1 프로세스 생성
2 프로세스가 파일 생성시간을 변경
3 네트워크 연결
4 Sysmon 서비스 상태 변경
5 프로세스 종료
6 드라이버 로드
7 이미지 로드 (“-l” 옵션으로 활성화 필요)
8 다른 프로세스에서 스레드 생성
9 RawAccessRead 탐지 (프로세스가 “\\.\” 표기법 이용하여 드라이브 접근시)
10 특정 프로세스가 다른 프로세스 Access (ex. Mimikatz > lsass.exe)
11 파일 생성 (생성 및 덮어쓰기)
12 레지스트리 이벤트 (키 값 생성 및 삭제)
13 레지스트리 이벤트 (DWORD 및 QWORD 유형의 레지스트리 값 수정)
14 레지스트리 이벤트 (키 및 값 이름 변경)
15 FileCreateStreamHash (파일 다운로드와 관련된 Zone.identifier 확인)
17 PipeEvent (파이프 생성)
18 PipeEvent (파이프 연결)
19 WmiEventFilter 활동이 감지 됨 (악성코드 실행시 사용될 가능성 있음)
20 WmiEventConsumer 활동이 감지 됨
21 WmiEventConsumerToFilter 활동이 감지 됨
255 Sysmon 오류

[표 1] Sysmon Event ID

ELK + Beats

ELK란 Elasticsearch, Logstash, Kibana의 3가지 오픈소스를 부르는 말이다.

Elasticsarch : 분산 검색 엔진, 데이터 저장

Logstash : 입력 값 필터링

Kibana : 시각화 도구

Beats : 시스템 정보 및 파일 로그 전달 등의 기능

위에 4가지 도구를 이용하여 Sysmon 모니터링 도구를 만들고자 한다. 기본적으로 ELK를 설치하는 방법은 지난 포스팅에서 설명하였기 때문에 자세한 ELK 설치 방법에 대해서는 따로 언급하지 않고 설정과 관련된 부분을 다루려고 한다. 설치와 관련된 정보는 ELK 스택의 사이트(https://www.elastic.co)에서 얻을 수 있다.

전체적인 구성도는 Sysmon을 설치한 파일에 Winlogbeats를 설치하고 해당 데이터를 ELK가 설치된 서버로 전송하는 방식이다. 각각 Logstash는 5044포트로 데이터를 받아 Elasticsearch로 보내고 Kibana의 5601포트로 결과값을 확인 가능하다.

[그림 4] Sysmon + ELK 구성도

 Beats 설정

Beats는 경량 로그 수신기로 여러 종류가 있다. 이 중 Winlogbeats는 Eventlog를 전달해주는 역할을 한다. Sysmon을 전달하기 위해서 Sysmon이 설정된 시스템에 Winlogbeats를 설치하고 다음과 같이 설정 파일을 변경해준다. 설정 파일의 내용은 다음과 같다. (winlogbeat.yml)

[그림 5] Winlogbeat.yml

아래와 같은 명령어로 실행이 가능하며 ELK 사이트에서 서비스로 등록하는 방식을 참고하면 서비스로 등록하여 사용이 가능하다.

C:\Users\Administrator\Desktop\winlogbeat>.\winlogbeat.exe -c .\winlogbeat.yml -e

Logstash 설정

Beats로 전달 받은 데이터를 더욱 효율적으로 보기 위해 Logstash를 이용하여 각각의 값에 항목을 지정해 준다. Logstash의 필터링은 Logstash의 conf 파일을 수정하여 만들 수 있다.

Sysmon의 데이터 중에 의미있는 값을 선별하게 위해 conf 파일을 작성하였다. 하지만 이는 사용자의 설정에 따라 변경되어야하며 필터링으로 인해 더 다양한 이벤트를 탐지할 수 있다.

이벤트에 대한 conf파일을 만들기 위해서는 우선 입력되는 데이터에 대하여 확인하는 것이 중요하다.

입력되는 데이터는 다음과 같다.

[그림 6] Winlogbeat 입력값

입력되는 데이터 부분중 특히 message부분에서 의미있는 값을 찾아낼 수 있다. X-pack 설치후 활용이 가능한 Grok Debugger나 웹페이지 http://grokdebug.herokuapp.com/를 이용하여 Grok 표현식을 통해 message 부분에서 특정 부분을 추출해서 사용할 수 있다.

[그림 7] Grok Debugger – Xpack

input {

beats {

port => 5044

}

}

 

filter {

if ([event_data][hashes][altsha1]) {

mutate {

split => [“[event_data][hashes][altsha1]” , “=”]

add_field => { “[event_data][hashes][sha1]” => “%{[event_data][hashes][altsha1]][1]}” }

remove_field => [ “[event_data][hashes][altsha1]”]

}

}

if ([event_data][hashes][altmd5]) {

mutate {

split => [“[event_data][hashes][altmd5]” , “=”]

add_field => { “[event_data][hashes][md5]” => “%{[event_data][hashes][altmd5]][1]}” }

remove_field => [ “[event_data][hashes][altmd5]”]

}

}

if ([event_data][hashes][altsha256]) {

mutate {

split => [“[event_data][hashes][altsha256]” , “=”]

add_field => { “[event_data][hashes][sha256]” => “%{[event_data][hashes][altsha256]][1]}” }

remove_field => [ “[event_data][hashes][altsha256]”]

}

}

if ([event_data][hashes][altimphash]) {

mutate {

split => [“[event_data][hashes][altimphash]” , “=”]

add_field => { “[event_data][hashes][imphash]” => “%{[event_data][hashes][altimphash]][1]}” }

remove_field => [ “[event_data][hashes][altimphash]”]

}

}

if ([event_id] == 1) {

grok {

match => { “message” => “http://%{IP:[remote_ip]}/%{GREEDYDATA:[event_data][powershell_file]}'” }

}

}

}

 

output {

stdout { codec => rubydebug }

elasticsearch {

hosts => [“localhost:9200”]

index => “logstash-winlogs”

}

}

[그림 8] logstash – sysmon.conf (참조: http://www.ubersec.com/2017/12/14/sysmon-elk-monitoring-integration-and-apt34-tools/)

Kibana 설정

입력된 데이터를 시각화하는 Kibana에서는 Sysmon 로그를 이용하여 대시보드를 만들어 볼 수 있다. Kibana의 index-pattern은 Logstash에서 설정한 output의 index 부분으로 정의된다.

[그림 9] Kibana – Discover

이렇게 index된 데이터를 불러와서 Kibana Visualize 작업을 실시한 후 여러 개의 Visualize가 모여서 나만의 Dashboard를 만들 수 있다.

[그림 10] Kibana – Dashboard

X-pack에서 추가된 머신 러닝 기능과 담당자의 메일 등으로 Alert가 가능한 6.0 이상의 버전을 이용하면 더 효율적으로 사용이 가능하다.

[그림 11] Kibana -Xpack 이상 행위 탐지

결론

추가적으로 Windows의 감사정책 및 이벤트 로그를 변경하면 Sysmon에서 로깅하는 데이터 이외에도 의미 있는 데이터를 얻을 수가 있다. 이렇게 전달되는 데이터가 다양해지면 이를 ELK를 이용하여 더 많은 이상행위를 탐지할 수 있다.

이번 포스팅에서 소개한 Sysmon과 ELK가 백신이 함께 시스템을 방어한다면 탐지가 어려운 APT 공격에 충분한 대응 방안이 될 수 있다고 생각한다. 최소한의 비용으로 증가되는 위협에 대응해보자.

참조

https://docs.microsoft.com/en-us/sysinternals/downloads/sysmon

https://github.com/SwiftOnSecurity/sysmon-config

https://cyberwardog.blogspot.kr/2017/03/building-sysmon-dashboard-with-elk-stack.html

http://www.ubersec.com/2017/12/14/sysmon-elk-monitoring-integration-and-apt34-tools/

DOS Batch Script 명령어 정리

주석

  • 주석 명령은 설명문으로 실행되지 않는다.
  • rem 으로 실행하고 뒤에 주석문(아무 스트링)을 입력하면 된다. 주석은 프로그래밍시에 간략한 설명을 위한 것이다.
  • @rem test message… : 앞에 @를 붙이면 배치파일 실행시 rem 커맨드 출력이 안되도록 한다. 물론 그 전에 @echo off을 해 두었다면 @을 붙일 필요없다.
  • 더 간단하게는 :: 으로 시작하면 주석이 된다. 이것은 커맨드 출력도 되지 않아 더 간편히 사용할 수 있다. rem과 다르게 아예 없는 것으로 취급된다.

변수와 출력

  • dos batch는 파일 확장자를 .bat 또는 .cmd로 하여 메모장으로 텍스트 파일로 작성하면 된다.
  • 기본 적인 출력은 “echo” 커맨드가 있다. 뒤에 출력할 내용을 적으면 된다.
  • 출력 내용에 변수명을 적어 변수값을 출력할 수 도 있다. 또한 변수중에는 미리 시스템에서 정의된 값들도 있어서 유용하다.
  • 변수 설정은 set으로 변수이름과 값을 =으로 할당한다.
  • 변수 사용시에는 변수 이름 앞뒤로 %를 붙인다. 변수 삭제는 빈 값을 할당한다. (빈 값이 있는 변수로 만드는 것이 아니라 변수 자체를 삭제한다는 의미!)

SET FOO=hello world
echo %FOO%
echo %FOO%xxx%FOO%
SET FOO=

  • for문의 변수 이름은 커맨드창에서 바로 실행할 때 영문자앞에 %를 붙인다. 그러나, Dos batch file(.bat)에서 for문의 변수 영문자 앞에 %% 이렇게 %를 두 개 붙인다!
c:\> copy con test1.bat
@echo off
@rem this is a test batch...
set aaa=hello
echo %aaa%
echo %1
^Z

c:\> test1 kim
hello
kim
  • @echo off는 이후에 echo 실행명령은 출력하지 않고, 결과만 출력하도록 한다.
  • batch 파일 실행시 뒤에 파라미터를 줄 수 있는데, 순서대로 %1, %2, … 이렇게 변수로 사용할 수 있다.
  • 줄바꿈. 엔터 입력. 빈 줄 출력

echo.

  • 공백으로 시작하는 문자열 출력

echo. aaa
echo aaa (이것도 이제는 가능함. 앞에 공백 두 개)

  • 특수 문자 출력시 앞에 ^를 사용

echo ^< 이것은 꺾은 괄호 ^>
echo ^| 파이프
echo ^^ 두 개 입력시 하나 출력

스트링 처리

  • 문자열 추출 mid / substr

FOO 변수의 값에서 인덱스 6부터 3글자를 추출. (인덱스는 0부터 시작) 뒤에 수를 생략하면 끝까지를 의미함. -1은 마지막 바로 한글자를 의미.
set BAR=%FOO:~6,3%
set BAR=%FOO:~5%
set BAR=%FOO:~-3% : FOO가 파일명일떄 마지막 세글자(확장자명)을 가져온다.

연산

  • 수 값을 할당하거나 연산하려면 SET /a를 사용한다.

set /a num=4*8+8/2+122
set /a num=1
set /a num+=2
if %num% GEQ 3 echo big

환경 변수

%CD% : 현재 작업 디렉터리
%DATE% : date 커맨드와 같은 포맷의 날짜
%TIME%
%RANDOM% : 0~32767 범위의 수
%ERRORLEVEL%
%CMDCMDLINE%

파라미터

  • 파라미터는 %1, %2, 등으로 받는다. (%0은 배치파일 이름 자체임. %9까지 가능)
  • %*은 모든 파라미터를 의미함.
  • 파리미터 내부에 공백이 있으면 커맨드상에서 파라미터를 “로 둘러싼다. 단, 스크립트에서 “를 제거하고 받으려면 %~1, %~2 로 받는다.
  • 파라미터가 없으면 종료

if “%1” == “” goto :eof
파라미터에 “를 추가해 주어야 한다.’

Redirect

  • stderr까지 파일로 기록

cmd /c “test.exe” > “output.txt” 2>&1

  • 실행만 하고 출력은 없앰 (no output)

dir > nul
nul 이라는 파일은 생성되지 않는다. (NUL 대소문자 상관없음. 주의! L이 한 개임.)

type nul > a
0바이트짜리 a라는 파일 생성

program 2 > output.txt
stderr 출력을 파일로 기록

배치내에서 배치 실행하기

call b.bat param1 param2

  • 동시 실행

start /d “directory…” /b program.exe
start /d “directory…” /b program.exe

디렉터리 경로명 이동

cd /d e:\temp

반복문 for

  • integer 증가

for /L %%n in (1,1,100) do net user %%n /add
1부터 100까지 증가하고, 숫자로 계정명으로 사용자를 추가한다.
(for의 변수는 커맨드로 실행시에는 %하나 batch file인 경우는 %% 두개를 사용한다.)

  • 1부터 5까지 출력

for /L %n in (1,1,5) do echo %n

  • 1부터 5까지 출력. 2씩 건너뜀.

for /L %n in (1,2,5) do echo %n
1,3,5 각각 한 줄로 출력됨.

goto

  • 종료시

goto :eof 또는 goto:eof
eof 레이블은 만들필요없이 미리정의된 거라 그대로 사용 가능
또는 exit /b 0

  • 레이블 지정과 goto

레이블 지정시에는 앞에 :을 붙이고 goto 시에는 :를 빼야 한다.
:loop
echo infinite…
goto loop

Sleep

@rem 3sec sleep
@ping 1.2.3.4 -n 1 -w 3000 > NUL

IF

  • 조건 판단
  • 같은지 확인 == 앞 뒤에 공백은 없어도 됨.

if %var% == 1 goto done
echo a
:done
echo b

  • if else : 괄호, 공백 주의

if %var% == 0 (
echo a
) else (
echo b
)

  • /i 옵션 : 대소문자 구분 없이 비교. (case-insensitive)

사용자 입력/텍스트파일변수

  • yn 선택지 (or 스트링 입력)

set /p result=message (Y/N)?
echo %result%
빈 값을 검사하려면 아래 코드를 참고

@echo off
:: init var for empty string.
set "result="
set /p result=are you ok(y/n)?
if "%result%" == "" (
echo no input
goto :eof
)
if /i "%result%"=="y" goto YES
if /i "%result%"=="n" goto NO

echo your input is %result%

  • 텍스트 파일을 첫 행을 읽어 변수에 할당

set /p var=<%temp%\filename.txt

> copy con lines.txt
hello1
hello2
hello3
^Z
> set /p var=<lines.txt
> echo %var% %var%
hello1 hello1

디렉터리

  • 중간 디렉터리까지 모두 생성. mkdir 대신 md를 사용

md “a\b\c”

  • 하위 파일/디렉터리 모두 삭제. /s 옵션

rmdir /s “dirname”

기타

  • 종료 : exit

exit /b 0 : /b는 cmd창은 남겨둔다는 의미. 뒤의 숫자는 프로그램 종료 리턴값. (다른 배치에서는 이 값을 errorlevel 변수로 받아 사용할 수 있다.)

  • 파일 병합 / 붙이기 concate
  • 파일 세 개를 붙여서 하나의 파일로 만든다.

copy 1.txt + 2.txt + 3.txt out.new /b

  • 배치 파일에서 다른 배치 파일 실행하기

call b.bat : call을 사용한다. 그냥 b.bat로 실행하면? b.bat가 종료시 나머지 스크립트로 돌아오지 않고 종료된다.

[엘라스틱서치] Elasticsearch in action – 데이터 검색

엘라스틱서치는 루씬 검색 기능을 모두 사용해서 데이터를 검색할 수 있도록 풍부한 API를 제공한다. 엘라스틱서치는 그 형식 덕분에 다양한 조합으로 검색 요청을 만들 수 있다. 데이터에 사용할 적절한 필터 조합 쿼리를 찾는데 가장 나은 방법은 시험해보는 것이다. 프로젝트 데이터에서 원하는 가장 적합한 것을 찾기 위해 여러가지 조합을 시도해보는 것이 가장 중요하다.

 

  • 검색 요청과 검색 요청의 결과가 일반적으로 어떻게 보여질까?
  • 검색 API의 주요 구성 요소 중 하나인 쿼리와 필터 DSL를 알아본다.
  • 필터와 쿼리에 사용하는 가장 일반적인 방법 / 쿼리와 필터의 차이점
  • 엘라스틱서치가 도큐먼트의 점수를 어떻게 계산할까?

REST API 검색 요청은 처음 접속하려고 선택한 노드에 전송되고 검색 요청을 모든 샤드(주 또는 레플리카)로 보낸다. 모든 샤드에서 정렬 및 순위를 매긴 결과로부터 충분한 정보를 수집하면, 오직 반환될 도큐먼트 내용을 담고 있는 샤드만 해당 내용을 반환하도록 요청 받는다. 이런 검색 라우팅 기능은 설정할 수 있는데, “query_then_fetch”라 부르는 기본동작이다.

 

엘라스틱서치 검색 요청은 JSON 도큐먼트 기반 요청이거나 URL 기반 요청이다. 요청은 서버로 보내지고, 모든 검색 요청이 같은 형식을 따르기 때문에 개별 검색 요청을 변경할 수 있는 구성 요소에 대해 이해하는 것이 도움이 된다.

 

색인은 두 개의 샤드이고 샤드당 한 개의 복제본으로 구성한다. 도큐먼트를 찾고 점수를 산정한 후 상위 n개의 도큐먼트가 반환된다.

 

 

(1) 검색 범위 지정하기

모든 REST 검색 요청은 _search REST 종단점을 사용하고 GET이나 POST 요청 중 하나가 된다. 전체 클러스터를 검색하거나 또는 요청 URL에 색인 이름 또는 타입을 지정해서 범위를 제한할 수 있다.

 

일단 색인을 하면, 다중 색인을 검색하는 alias도 사용할 수 있다. 이 방식은 접근 가능한 날짜와 시간으로 구성한 이름의 색인을 이용해서 검색할 때 종종 사용한다. 즉, logstash-yyyymmdd 형식의 색인은 하나의 앨리어스로 logstash를 호출하지만 실은 전체 색인을 가리키게 된다. 기본 검색을 할 수도 있고 curl ‘localhost:9200/logstash/_search’처럼 전체 logstash 기반 색인에 한정할 수도 있다. 최고 성능을 내려면, 최소한의 색인과 타입을 사용하도록 쿼리를 제한하는 것이 좋다. 각 검색 요청이 모든 색인 샤드에 전송된다는 사실은, 더 많은 색인은 더 많은 샤드에 검색 요청이 전송된다는 것을 의미한다.

 

 

(2) 검색 요청의 기본 구성 요소

검색할 색인을 선택했다면, 검색 요청에 있어 가장 중요한 구성 요소를 설정해야 한다. 구성 요소는 반환할 도큐먼트 개수를 제어하고, 최적의 도큐먼트를 선택하게 하며, 원치 않는 도큐먼트는 결과에서 걸러내도록 한다.

 

  • query – 검색 요청에 있어 가장 중요한 요소다. 점수 기반으로 최적의 도큐먼트를 반환하거나 원치 않는 도큐먼트를 걸러내도록 설정한다. 이 구성 요소는 DSL 쿼리와 DSL 필터를 사용해서 구성한다.
  • size – 반환할 도큐먼트 개수를 의미한다.
  • from – size와 함께 Pagination에 사용한다. 다음 페이지 10개를 결정하기 위해 엘라스틱서치는 상위 20개를 산출해내야 한다는 점을 기억한다. 결과 집합이 커져서 중간쯤 어딘가의 페이지를 가져오는 것은 비용이 많이 들어가는 요청이 될 것이다.
  • _source – _source 필드는 어떻게 반환할 것인가를 명시한다. 기본값은 완전한 _source 필드를 반환하는 것이다. _source 설정으로 반환되는 필드를 걸러낼 수 있다. 색인된 도큐먼트가 크고 결과에서 전체 내용이 필요하지는 않을때 사용한다. 이 옵션을 사용하려면, 색인 매핑에서 _source 필드를 비활성화하지 않아야 한다. 필드와 _source간에는 차이가 있다.
  • sort – 기본 정렬은 도큐먼트 점수에 따른다. 그런데, 점수 계산이 필요없거나 동일 점수의 다수 도큐먼트가 예상된다면, 반환한 도큐먼트 결과로부터 가져올때 sort를 추가해서 원하는대로 순서를 제어할 수 있다.

 

기본 구성 요소 중 쿼리 구성 요소에 대해 알아본다. match_all 쿼리를 match 쿼리로 변경하고, 필터 DSL에서 쿼리 DSL의 filtered 쿼리를 사용하는 검색 요청으로 변경하는 term 필터를 추가할 수 있다. 그리고 필터와 쿼리의 차이점을 깊게 알아 본다.

 

다음 예제는 “Hadoop” 단어를 제목으로 포함하는 그룹을 찾기 위해 match 쿼리를 사용했다.

 

curl ‘localhost:9200/get-together/event/_search’ -d ‘{
“query”: {
“match”: {
“title”: “hadoop”
}
}
}’

쿼리는 3건의 이벤트를 반환한다. 쿼리를 실행해서 처음 일치하는 것의 점수를 확인한다. 첫 일치는 “Using Hadoop with Elasticsearch”라는 제목을 가진 도큐먼트이다. 이 검색을 H가 대문자인 “Hadoop” 단어로 검색하도록 변경할 수 있다. 결과는 같을 것이다.

 

필터가 쿼리와 유사하긴 해도 점수 매김과 여러가지 검색 기능 수행을 어떻게 적용하는지가 다르다. 쿼리가 특정 텀으로 점수 계산하는 것과 달리, 검색에서 필터는 “이 도큐먼트가 이 쿼리와 일치를 하는가”하는 단순 이진법의 예 또는 아니요 답변만을 반환한다.

 

 

필터는 이런 차이점 때문에 일반 쿼리를 사용하는 것보다 더 빠를 수 있고 캐시할 수도 있다. 필터를 이용해서 검색하는 것은 쿼리를 사용하는 일반 검색과 유사하게 보이지만, 실제는 그렇지 않다. 쿼리는 원래의 쿼리와 필터를 포함하는 “filtered” 맵으로 변경한다. 이 쿼리는 쿼리 DSL에서 filtered query로 부른다. filtered query는 두 개의 구성 요소. 즉, 쿼리와 필터를 포함한다.

 

$ curl 'localhost:9200/get-together/_search' -d '{
    "query": {
        "filtered": {
            "query": {
                "match": {
                    "title": "hadoop"
                }
        },
        "filter": {
            "term": {
                "host": "andy"
            }
        }
    }
}'

 

여기 “hadoop”으로 일치하는 이벤트를 위한 일반적인 쿼리처럼 필터가 사용되었으나, 필터는 “Hadoop” 단어를 위한 쿼리뿐만 아니라 특정 이벤트로 제한할 때에도 사용한다. 이 특정 필터 부분 내부에, host가 “andy”인 모든 도큐먼트를 찾기 위해 텀 필터가 사용되었다. 여기서 엘라스틱서치는 이 필터와 일치하는 도큐먼트인지 아닌지 보여주는 바이너리 비트 집합인 Bitset을 작성한다.

 

엘라스틱서치가 비트셋을 만들고 나서는 도큐먼트를 필터링하는데 사용할 수는 있으나 검색의 쿼리 일부분으로 검색하는 것은 아니다. 필터는 점수 계산이 필요한 도큐먼트를 제한한다. 제한된 도큐먼트 집합의 접수는 쿼리 기반으로 계산된다. 이런 이유로, 필터를 추가하는 것은 전체 쿼리를 단일 검색으로 결합하는 것보다 더 빠른다. 어떤 종류의 필터인가에 따라 엘라스틱서치는 비트셋 결과를 캐시할 수 있다. 필터를 다른 검색에 사용해도 비트셋을 다시 계산할 필요가 없다.

 

그러나 어떤 유형의 필터의 경우, 엘라스틱서치가 다시 사용되지 않을 것으로 판단하거나 비트셋 재생성 비용이 사소하다면 자동으로 캐시하지 않을 수 있다. 캐시하기 어려운 쿼리의 예로 최근 한 시간의 모든 문서로 결과를 제한하는 필터의 경우가 그러하다. 이 쿼리는 이를 실행할 때 매초 변경되어야 하므로 캐시할 이유가 없다. 추가로, 엘라스틱서치는 필터를 캐시해야 할지에 관해 수동으로 지정하는 기능을 제공한다. 이 모든 것은 필터를 가진 검색을 더 빠르게 만든다. 그러므로 가능하다면 쿼리의 일부분을 필터로 만들 필요가 있다.

 

비록 엘라스틱서치에서 쿼리하는 수많은 방법이 있지만, 어떤 쿼리는 색인에 데이터가 어떻게 저장되었는지에 의존하는 쿼리보다 더 나을 수 있다. 엘라스틱서치가 지원하는 쿼리의 서로 다른 타입을 알아보고, 쿼리에서 어떻게 사용하는지 알아보도록 하겠다. 어떤 쿼리가 데이터에 가장 적합한지 결정할 수 있도록 각각 성능에 대해서도 언급하고, 각 쿼리를 사용할 때의 장단점에 대해서 가늠해보도록 한다.

 

전체 도큐먼트를 반환하는 match_all 쿼리로 시작하여, 특정 필드에 대해 일치하는 다어로 결과를 제한하는 match 쿼리로, 그리고 특정 필드에 있는 텀을 사용해서 결과를 제한하는 텀 필터가지 사용해봤다. 그리고 query_string을 사용하는 방법도 존재한다. 이 쿼리는 URL 기반 검색에서 사용하게 된다.

 

 

MATCH_ALL 쿼리

이 필터는 모든 도큐먼트를 일치하게 한다. 도큐먼트 점수에 관해 신경쓰지 않을때라면, 쿼리 대신 필터 사용이 필요할때 match_all 쿼리가 상당히 유용하다. 또는 검색하는 색인과 타입 사이에서 모든 도큐먼트를 반환하고 싶을때 유용하다. 이 쿼리는 다음과 같은 형태다.

curl 'localhost:9200/_search' -d '{
    "query" : {
        "match_all": {}
    }
}'

 

 

검색에 쿼리 부분 대신 필터를 사용하면 쿼리는 아래와 같다.

curl 'localhost:9200/get-together/_search' -d '{
    "query": {
        "filtered": {
            "query": {
                "match_all": {}
            },
            "filter": {
                ... 필터 세부 내용 ...
            }
        }
    }
}'

 

거의 모든 것을 검색하기 때문에 검색엔진을 사용함에도 사용자에게는 유용해 보인다. Match_all 쿼리를 기본으로 사용하면 검색요청도 더 쉽게 만들 수 있다. 그러므로 쿼리 요소는 이 경우 완벽하게 생략할 수 있다.

 

 

QUERY_STRING 쿼리

엘라스틱서치 서버를 시작하고 실행할때, query_string 쿼리를 이용하면 쉽게 쿼리 결과를 얻을 수 있다. query_string 검색은 요청 URL로부터 또는 요청 본문을 전송하는 것으로부터 수행할 수 있다. 아래 예제는 “nosql”을 포함하는 도큐먼트를 검색하는데, 이 쿼리는 도큐먼트 한 건을 반환할 것이다.

// query_string 검색은 URL 파라미터처럼 전송
curl -X GET 'localhost:9200/get-together/_search?q=nosql&pretty'

// 같은 query_string 검색을 요청 본문처럼 전송
curl -X POST 'http://localhost:9200/get-together/_search?pretty' -d '{
    "query": {
        "query_string" : {
            "query" : "nosql"
        }
    }
}'

 

기본적으로, query_string 쿼리는 _all 필드를 검색한다. _all 필드는 모든 필드 결합으로 구성되어 있다. description:nosql 처럼 쿼리로 특정 필드를 지정하거나 요청 본문에 default_field를 지정하면 이를 변경할 수 있다.

curl -X POST 'localhost:9200/_search' -d '{
    "query": {
        "query_string" : {
            // 쿼리에 지정된 필드가 없기 때문에 기본 필드가 사용.
            "default_field": "description",
            "query": "nosql"
        }
    }
}'

 

추측할 수 있듯이, 이 문법은 단일 단어를 검색하는 것보다 더 많은 것을 제공한다. 내부적으로, 이는 모두 AND와 OR처럼 boolean 연산자로 서로 다른 텀을 검색하고 추가적으로 마이너스(-) 연산을 사용해서 결과로부터 도큐먼트를 제외하는 결합의 루씬 쿼리 문법이다. 다음 쿼리는 “nosql” 이름으로 모든 그룹을 검색하지만 description에 “mongodb”를 포함하지 않는다.

name:nosql AND -description:mongodb

 

1999년부터 2001년 사이에 생성한 모든 search와 모든 lucene 그룹은 다음과 같이 검색할 수 있다.

(tags:search OR tags:lucene) AND created_on:[1999-01-01 TO 2001-01-01]

 

query_string는 쿼리가 위력적이여서, 웹사이트 사용자에게 그대로 노출하면, 엘라스틱서치 클러스터가 위험할 수 있다. 사용자가 잘못된 형식으로 쿼리를 실행하면 예외 상황에 맞닥뜨리게 될 수 있다. 또한, 모든 것을 반환하는 조합을 만들 가능성도 있어서, 이는 클러스터에 리스크가 될 수 있다.

 

도큐먼트의 필드와 필드 내에 있는 문자열 검색을 허용하는 term, terms, match, multi_match 쿼리를 포함하는 query_string 쿼리는 다른 대체재로 교체하는 것을 추천한다. 적절한 대체재는 simple-query-string 쿼리인데, +,-,AND,OR를 사용하여 쉽게 접근 가능한 쿼리 문법으로 교체할 수 있다.

 

 

텀 쿼리와 텀 필터

텀 쿼리와 필터는 실행 가능한 가장 단순한 쿼리인데, 필드와 텀을 지정해서 도큐먼트 내에서 검색할 수 있다. 검색한 텀이 분석되지 않았기 때문에 완전히 일치하는 도큐먼트 결과만 찾는것은 것을 알아둔다. 엘라스틱서치에 의해 어떻게 텍스트를 개별적인 색인 조각으로 토큰을 만드는 지는 데이터 분석 파트에서 확인할 수 있다. 루씬에 익숙하다면, 텀쿼리가 직접적으로 루씬 TermQuery로 매핑된다는 것은 유용한 정보가 된다.

 

다음은 elasticsearch 태그로 그룹을 검색하는 텀 쿼리이다.

curl 'localhost:9200/get-together/group/_search' -d '{
	"query": {
		"term": {
			"tags": "elasticsearch"
		}
	},
	"_source": ["name", "tags"]
}'

{
	...
	"hits": [
		{
			"_id": "3",
			"_index": "get-together",
			"_score": 1.0769258,
			"_type": "group",
			"_source": {
				"name": "Elasticsearch San Francisco",
				"tags": [
					"elasticsearch",
					"big data",
					"lucene",
					"open source"
				]
			}
		},
		{
			"_id": "2",
			"_index": "get-together",
			"_score": 0.8948604,
			"_type": "group",
			"_source": {
				"name": "Elasticsearch Denver",
				"tags": [
					"denver",
					"elasticsearch",
					"big data",
					"lucene",
					"solr"
				]
			}
		}
	],
	...
}

 

텀 쿼리처럼 텀 필터는 점수에 영향을 미치지 않고 텀을 포함하는 도큐먼트의 제한된 결과가 필요할 때 사용할 수 있다. 점수를 사용한 이전 예제의 도큐먼트 점수를 다음 예제와 비교하자. 필터가 계산에 방해가 되지도 점수에 영향을 미치지도 않는다는 것을 알게 될 것이다. Match_all 쿼리 대문에 모든 도큐먼트의 점수는 1.0이 된다. 도큐먼트 점수는 필터가 쿼리대신 사용되었으므로 이제 상수가 된다.

curl 'localhost:9200/get-together/group/_search' -d '{
	"query": {
		"filtered": {
			"match_all": {}
		},
		"filter": {
			"term": {
				"tags": "elasticsearch"
			}
		}
	},
	"_source": ["name", "tags"]
}'

{
	...
	"hits": [
		{
			"_id": "3",
			"_index": "get-together",
			"_score": 1.0,
			"_type": "group",
			"_source": {
				"name": "Elasticsearch San Francisco",
				"tags": [
					"elasticsearch",
					"big data",
					"lucene",
					"open source"
				]
			}
		},
		{
			"_id": "2",
			"_index": "get-together",
			"_score": 1.0,
			"_type": "group",
			"_source": {
				"name": "Elasticsearch Denver",
				"tags": [
					"denver",
					"elasticsearch",
					"big data",
					"lucene",
					"solr"
				]
			}
		}
	],
	...
}

 

 

텀즈 쿼리

텀 쿼리와 유사하게, 텀즈(term이 아닌 terms) 쿼리로 도큐먼트 필드에서 다중 텀으로 검색할 수 있다. 예를 들어, 다음 예제는 “jvm”, “hadoop” 중 어느 하나와 일치하는 태그의 그룹을 검색한다.

curl 'localhost:9200/get-together/group/_search' -d '{
	"query": {
		"terms": {
			"tags": ["jvm", "hadoop"]
		}
	},
	"_source": ["name", "tags"]
}'

{
	...
	"hits": [
		{
			"_id": "1",
			"_index": "get-together",
			"_score": 0.33779633,
			"_type": "group",
			"_source": {
				"name": "Denver Clojure",
				"tags": [
					"clojure",
					"denver",
					"function programming",
					"jvm",
					"java"
				]
			}
		},
		{
			"_id": "4",
			"_index": "get-together",
			"_score": 0.22838624,
			"_type": "group",
			"_source": {
				"name": "Boulder/Denver big data get-together",
				"tags": [
					"big data",
					"data visualization",
					"open source",
					"cloud computing",
					"hadoop"
				]
			}
		}
	]
}

 

쿼리 일치 전에 도큐먼트에서 최소 개수의 텀 일치를 강제하려면, minimum_should_match 파라미터를 지정한다. 이외에 다중 쿼리와 단일 쿼리를 결합할 필요가 있을때, 다중 텀 쿼리를 결합한 복합 쿼리를 작성할 수도 있다.

 

curl 'localhost:9200/get-together/group/_search' -d '{
	"query": {
		"terms": {
			"tags": ["jvm", "hadoop", "lucene"],
			"minimum_should_match": 2
		}
	}
}'

 

 

매치 쿼리와 텀 필터

텀 쿼리와 유사하게 매치 쿼리는 검색하려는 필드와 검색하려는 문자열을 포함하는 해시맵인데, 필드나 한번에 모든 필드를 검색하는 _all 필드가 올 수 있다. 다음 예제는 name 필드에 “elasticsearch”를 포함하는 그룹을 검색하는 매치 쿼리다.

curl 'localhost:9200/get-together/group/_search' -d '{
	"query": {
		"match": {
			"name": "elasticsearch"
		}
	}
}'

 

매치 쿼리는 몇몇 서로 다른 방식으로 동작할 수 있다. 가장 주요한 두 가지의 기능은 boolean과 phrase다.

 

 

(1) BOOLEAN 쿼리

기본적으로, 쿼리 매치는 Boolean 기능과 OR 연산을 사용한다. 예를 들어 “Elasticsearch Denver” 텍스트를 검색한다면 엘라스틱서치는 “Elasticsearch OR Denver”로 검색해서 “Elasticsearch Amsterdam”과 “Denver Clojure Group” 모두로부터 get-together groups가 일치할 것이다.

 

“Elasticsearch”와 “Denver”를 모두 포함하는 결과를 검색하려면, 맵과 추가하는 연산자 필드 설정에 들어가는 일치 필드 이름을 수정하면서 연산자를 변경한다.

curl 'localhost:9200/get-together/_search' -d '{
	"query": {
		"match": {
			"name": {
				"query": "Elasticsearch Denver",
				"operator": "and"
			}
		}
	}
}'

 

 

(2) PHRASE 쿼리

도큐먼트 내에서 각 단어의 위치에 따른 leeway 값처럼 특정 구를 검색할때 phrase 쿼리가 유용하다. Leeway는 slop으로 불리는데 구문 내에서 토큰 사이의 거리를 표현하는 수치 값이다. get-together의 그룹 name을 기억해 내려 할때, “Enterprise” 단어와 “London” 단어는 기억하나 name의 나머지는 기억하지 못한다고 하자. “enterprise london” 구문을 기본값 0 대신 slop을 1 또는 2로 설정해서 완전한 그룹 제목을 몰라도 구문을 포함하는 결과를 찾아 검색할 수 있다.

curl 'localhost:9200/get-together/group/_search' -d '{
	"query": {
		"match": {
			"name": {
				"type": "phrase" // 일반 match 쿼리 대신 match phrase 쿼리 사용
				"query": "enterprise london",
				"slop": 1 // slop에 1을 지정해서 텀간 leeway 거리를 가지도록.
			}
		}
	}
}'

 

 

Phrase_prefix 쿼리

Match_phrase 쿼리와 유사하게 match_phrase_prefix 쿼리는 phrase로 검색하는 것에 더해서 phrase 내에서 마지막 텀에 프리픽스 매칭을 허용한다. 이 기능은 검색을 제안하는 검색창에서 사용자가 검색 텀을 입력하는 동안 자동완성을 제공하는 데 정말 유용하다. 이런 유형의 기능으로 검색을 사용할 때, max_expansions 설정을 사용해서, 검색이 반환할 이해 가능한 수준의 총 소요 시간 내에서 확장할 프리픽스의 최댓값을 설정하는 것이 좋다.

curl 'localhost:9200/get-together/group/_search' -d '{
	"query": {
		"match": {
			"name": {
				"type": "phrase_prefix",
				"query": "Elasticsearch den",
				"max_expansions": 1
			}
		}
	},
	"_source": ["name"]
}'

 

Boolean과 phrase 쿼리는 사용자 입력을 받아들이는 데 훌륭한 선택이 된다. Query_string 쿼리와 다르게 매치 쿼리가 +,-,ㅡ?,! 같은 예약된 문자를 막지 않으면서 오류 발생이 가장 적은 방식으로 사용자 입력을 그대로 넘기도록 허용하기 때문이다.

 

(1) MULTI_MATCH로 다중 필드 일치

비록 multi_match 쿼리가 텀즈 쿼리처럼 필드에서 다중 일치로 검색하는 기능으로 고려해볼 수 있겠지만, 이 기능은 다소 다르다. 다만, 다중 필드의 값을 검색하도록 허용한다. 이는 get-together 예제에서 그룹 name과 description 문자열로 검색하기를 원하는 곳에 유용할 수 있다.

 

curl 'localhost:9200/get-together/_search' -d '{
	"query": {
		"multi_match": {
			"query": "elasticsearch hadoop",
			"fields": ["name", "description"]
		}
	}
}'

 

매치 쿼리가 phrase 쿼리, prefix 쿼리 또는 phrase_prefix 쿼리로 전환할 수 있는 것처럼, multi_match 쿼리는 type 키를 추가해서 phrase 쿼리 또는 phrase_prefix 쿼리로 전환할 수 있다. Multi_match 쿼리는 검색을 위해 단일 필드 대신 다중 필드를 지정할 수 있다는 것을 제외하고는 매치 쿼리와 완전히 비슷하다.

 

매치 쿼리를 사용하면 어떠한 것도 검색할 수 있는데, 이는 대부분의 경우 기본적으로 사용할 수 있는 쿼리 타입이라 할 수 있어, 가능한 이를 사용하도록 강하게 추천한다.

 

bool 쿼리

Bool 쿼리는 몇 개의 쿼리라도 특정 부분이 must, should, must_not로 데이터가 일치하는지 명시하게 하는 쿼리 구문을 이용해서 단일 쿼리에 결합할 수 있다.

  • bool 쿼리로 must 매치를 지정한다면, 쿼리가 반환하는 오직 일치하는 결과만 받는다.
  • should 매치를 지정하면, 도큐먼트가 반환하는 특정 개수의 구문이 일치해야 한다는 의미다.
  • must 구문이 지정되지 않으면, 도큐먼트로부터 반환되는 것으로부터 일치하는 적어도 하나는 가져야 한다.
  • 마지막으로 must_not 구문은 일치하는 도큐먼트가 결과셋에서 제외하는데 사용한다.
bool 쿼리 절 이진 연산 대응 의미
must 다중 절을 결합하기 위해 이진 and 연산을 사용 (query1 AND query2 AND query3) must 절에서 검색은 도큐먼트가 일치해야 한다. 소문자 and는 함수이고, 대문자 AND는 연산자이다.
must_not 이진 not 연산으로 다중 절 결합 must_not 절에서 검색은 도큐먼트의 부분이 되지 않아야 한다. 다중 절은 이진 not 메소드에서 결합한다.
should 이진 or 연산으로 다중 절 결합
(query1 OR query2 OR query3)
should 절에서 검색은 이진 OR(query1 OR query2 OR query3)와 유사하게 도큐먼트가 일치하거나 그렇지 않을 수 있다. 그러나 최소 minimum_should_match 파라미터로 이 갯수만큼을 일치해야 한다. (must가 존재하지 않으면 기본값은 1이고, must가 존재한다면 0이다)

 

David가 참성한(attendees 텀) 이벤트를 검색하는데, Clint나 Andy 중 하나는 참석해야 하고, June 30, 2013보다 오래되지 않아야 한다.

curl 'localhost:9200/get-together/_search' -d '{
	"query": {
		"bool": {
			"must": [
				{
					"term": {
						"attendees": "david"
					}
				}
			],
			"should": [
				{
					"term": {
						"attendees": "clint"
					}
				},
				{
					"term": {
						"attendees": "andy"
					}
				}
			],
			"must_not": [
				{
					"range": {
						"date": {
							"lt": "2013-06-30T00:00"
						}
					}
				}
			],
			"minimum_sould_match": 1
		}
	}
}'

 

bool 필터

Bool 쿼리의 필터 버전은 쿼리 버전처럼 거의 동일한 역할을 하지만, 쿼리 대신 필터를 결합한다. 이전 예제의 필터에 해당하는 것은 다음과 같다. 단, bool 필터는 minimum_sould_match 속성을 제공하지 않는다.

curl 'localhost:9200/get-together/_search' -d '{
	"query": {
		"filtered": {
			"query": {
				"match_all": {}
			},
			"filter": {
				"bool": {
					"must": [
						{
							"term": {
								"attendees": "david"
							}
						}
					],
					"should": [
						{
							"term": {
								"attendees": "clint"
							}
						},
						{
							"term": {
								"attendees": "andy"
							}
						}
					],
					"must_not": [
						{
							"range": {
								"date": {
									"lt": "2013-06-30T00:00"
								}
							}
						}
					]
				}
			}
		}
	}
}'

 

query_string과 매치 쿼리같은 범용 쿼리는 검색차에서 사용자가 입력한 단어로 그런 쿼리를 실행할 수 있어서 특히 유용하다. 검색 범위를 좁히는 목적으로 특정 사용자 인터페이스는 검색창 옆에 최근 생성된 그룹을 검색하도록 하는 달력 위젯이나 특정 위치에서 발생한 이벤트를 필터링하려는 체크 상자 같은 또 다른 요소를 포함하기도 한다.

 

(1) 범위 쿼리와 필터

특정 범위 사이의 숫자, 날짜 및 문자열까지고 사용할 수 이쓴 값으로 쿼리하는 데 사용한다. 범위 쿼리를 사용해서 필드의 상위 및 하위 값을 지정한다.

curl 'localhost:9200/get-together/_search' -d '{
	"query": {
		"range": {
			"created_on": {
				"gt": "2012-06-01",
				"lt": "2012-09-01"
			}
		}
	}
}'

curl 'localhost:9200/get-together/_search' -d '{
	"query": {
		"filtered": {
			"query": {
				"match_all": {}
			}
		},
		"filter": {
			"range": {
				"created_on": {
					"gt": "2012-06-01",
					"lt": "2012-09-01"
				}
			}
		}
	}
}'

범위 쿼리는 문자열 범위도 지원한다. 범위 검색을 사용할 때 필터가 더 나은 선택인지 신중하게 생각하는게 좋다. 바이너리 매치를 가지는 범위 쿼리로 들어간 도큐먼트는 범위 쿼리가 되는데 필요하지 않기 때문이다. 쿼리로 만들지 필터로 만들지 확실치 않다면 필터로 만드는 것을 권장한다. 범위 쿼리를 만드는데 99% 경우, 필터가 옳은 선택이다.

 

프리픽스 쿼리와 필터

텀 쿼리와 유사하게 프리픽스 쿼리와 필터는 검색하기 전에 분석이 안된 프리픽스를 포함하는 텀을 검색하도록 해준다. 예를 들어, “liber”로 시작하는 모든 이벤트의 색인 검색은 다음 쿼리를 사용한다.

curl 'localhost:9200/get-together/event/_search' -d '{
	"query": {
		"prefix": {
			"title": "liber"
		}
	}
}'

curl 'localhost:9200/get-together/event/_search' -d '{
	"query": {
		"filtered": {
			"query" : {
				"match_all": {}
			},
			"filter": {
				"prefix": {
					"title": "liber"
				}
			}
		}
	}
}'

검색 프리픽스는 전송 전에는 분석되지 않으므로, “liber”를 “Liber”로 변경하여 검색요청을 보내면 색인에 소문자로 된 텀을 찾을 수 없다. 이는 엘라스틱서치가 도큐먼트를 분석하고 쿼리하는 방식때문이다. 이 기능때문에 프리픽스 쿼리는 텀이 색인의 일부분일때 사용자가 입력한 부분 텀의 자동완선에 있어서 좋은 선택이다. 예를 들어, 존재하는 카테고리가 이미 알려져 있을때 카테고리 입력창을 제공할 수있다. 사용자가 색인의 일부분인 텀을 입력하고 있다면, 사용자의 검색창에 입력하는 텍스트를 소문자로 변경한 다음 결과를 보여주는 어떤 다른 결과를 보여주기 위해 프리픽스 쿼리를 사용할 수 있다.

 

프리픽스 쿼리로부터 매칭 결과를 가지고 있을때 사용자가 입력하는 도중에 제안처럼 그들을 제공할 수 있다. 그러나 결과에서 텀을 분석하거나 fuzziness 값을 지정하기를 원하다면, 자동완성 기능을 위해 match_phrase_prefix 쿼리를 사용하는 게 아마 나을 것이다.

출처: https://12bme.tistory.com/477 [길은 가면, 뒤에 있다.]

ORACLE JOB 등록방법 (simple)

오라클 자체적으로 프로시저, 패키지, 등의 OBJECT 를 ORACLE JOB QUEUE에 등록후 스케쥴링 하여 사용할수 있습니다.

단, ORACLE PARAMETER 의 JOB_QUEUE_PROCESSES가 0보다 커야 JOB 스케쥴링이 동작한다는것에 유의하세요.

ALTER SYSTEM SET JOB_QUEUE_PROCESSES = 10 ; –변경

# DBMS_JOB 패키지의 프로시저

DBMS_JOB.SUBMIT( );          : JOB 등록

DBMS_JOB.REMOVE( );        : 제거

DBMS_JOB.CHANGE( );        : 변경

DBMS_JOB.NEXT_DATE( );   : JOB의 다음 수행시간 변경

DBMS_JOB.INTERVAL( );       : JOB의 실행 CYCLE 지정

DBMS_JOB.WHAT( );              : JOB 수행 으로 등록된 OBJECT 를 변경

DBMS_JOB.RUN( );                : JOB을 수동으로 실행

BEGIN
DBMS_JOB.RUN(‘4’);  — JOB 조회 후 번호 기술
END;

 

# SUBMIT 프로시져를 이용한 JOB등록 예제

DECLARE
X NUMBER;
BEGIN
SYS.DBMS_JOB.SUBMIT (
JOB       => X
,WHAT      => ‘실행할 OBJECT’
,NEXT_DATE => TO_DATE(’17-11-2007 09:00:00′,’DD/MM/YYYY HH24:MI:SS’)
,INTERVAL  => ‘TRUNC(SYSDATE) + 1 + 9/24’
,NO_PARSE  => TRUE
);
SYS.DBMS_OUTPUT.PUT_LINE (‘JOB NUMBER IS:’|| TO_CHAR (X)) ;
END;

# INTERVAL을 세팅

1. 10분간격으로 실행

SYSDATE + 1/24/6

2. 현재 시간으로 부터 다음 날 현재 시간에 실행 (매일)

SYSDATE + 1    — 지금이 오후3시면 다음날 오후 3시 에 매일매일 실행

3. 매일 새벽 5시

TRUNC(SYSDATE) + 1 + 5 / 24

4. 매일 밤 10시

TRUNC(SYSDATE)  + 20 / 24

# JOB의 확인

SELECT * FROM USER_JOBS;

NEXT_DATE 을 통해 다음 실행 예정인 시각을 확인

# 자세한 사항은 아래를 참고

HTTP://WWW.PSOUG.ORG/REFERENCE/DBMS_JOB.HTML