'apache'에 해당하는 글 5건

Exclude log4j2

Daily/Prog 2021. 12. 17. 20:59

log4j

 

ECR 에서 log4j2 사용중인 이미지들 깜빡하고 있었는데 AWS 에서 친절히 메일이 왔다.

 

You are receiving this communication because your account has container images stored in Amazon Elastic Container Registry (ECR). While not all container images are impacted by this CVE, your images may be affected if they are using Java with Apache Log4j in certain configurations. Amazon Inspector scans container images stored in Amazon ECR for software vulnerabilities to generate Package Vulnerability findings and is able to detect this issue in container images. You can turn on enhanced scanning from ECR [2] or enable Inspector from Inspector console to discover this issue in your images[3].

 

계정에 Amazon Elastic Container Registry(ECR)에 저장된 컨테이너 이미지가 있기 때문에 이 통신을 수신하게 되었습니다. 모든 컨테이너 이미지가 이 CVE의 영향을 받는 것은 아니지만 특정 구성에서 Apache Log4j와 함께 Java를 사용하는 경우 이미지가 영향을 받을 수 있습니다. Amazon Inspector는 Amazon ECR에 저장된 컨테이너 이미지에서 소프트웨어 취약성을 스캔하여 패키지 취약성 결과를 생성하고 컨테이너 이미지에서 이 문제를 감지할 수 있습니다. ECR[2]에서 향상된 스캔을 켜거나 Inspector 콘솔에서 Inspector를 활성화하여 이미지에서 이 문제를 발견할 수 있습니다[3].

 

log4j2 취약점이 추가로 계속 발생하고 있다. 2.15 에서 2.16 버전으로 업데이트...

확인하기도 귀찮다. 자꾸 신경쓰이게 하지 말고, logback 쓰고 log4j2 는 그냥 꼬죠.

 

// build.gradle
configurations {
    implementation.exclude group: "org.apache.logging.log4j"
}

 

spring 종속성을 사용한다면,,

 

// gradle
ext['log4j2.version'] = '2.17.2'

 


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

 

우와... 난 처음 글을 쓰는 거라고 생각했는데, 약 15년 전에 tomcat5 를 가지고 연동했던 글이 있네. 그 동안 아파치는 10년이 지나도록 apache3 도 내지 않고 있고...ㅋ

 

이렇게 사용하는 이유?는 성능을 위해서 일 수도 있겠고, 리소스 중복 줄이기나, 아파치의 특정 기능을 반드시 사용해야 하거나... 하겠지만, WAS 에서 인스턴스를 1개 정도만 사용한다면 글쎄... jmeter 등으로 테스트 해보고 결정하라. 인스턴스가 여러 개이고 동일한 정적 리소스를 사용한다면, 또 그 양이 방대하다면 리소스 중복을 줄일 수 있다는 이유로 apache 를 사용해 볼 만하다. 아니면 .htaccess? 아니면 php 랑 같이 쓴다던가. 아무튼... 이런저런 이유로 이 둘을 연동해야 한다면 해 봐야지.

 

테스트 환경 : CentOS 7 / Apache 2.4 / Tomcat 8.5 (instance1~3)
테스트 목표 : http://serverIP 80포트로 각 인스턴스에 AJP 통신 확인.(로드밸런싱 용도 아님)

 

 

1. Tomcat server.xml 설정 

 

(Apache / Tomcat 이 설치되어 있다고 가정)

$ vi /app/tomcat/instance1/conf/server.xml
<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector protocol="AJP/1.3"
           address="::1"
           port="8009"
           secretRequired="false"
           redirectPort="8443" />

 

server.xml 에 AJP 관련 요소를 수정해야 한다. AJP(Apache JServ Protocol)은 웹서버와 WAS 간에 통신이 가능한 프로토콜이다. 우선 주석을 해제하고 인스턴스 별로 ajp port 와 https redirectPort 를 지정한다. secretRequired="false" 를 지정하지 않으면 아래의 에러를 만나게 된다.

 

Caused by: java.lang.IllegalArgumentException: The AJP Connector is configured with secretRequired="true" but the secret attribute is either null or "". This combination is not valid.

 

 

2. Tomcat Connectors (mod_jk) 설치

의존 라이브러리 설치

 

# yum install gcc gcc-c++ httpd-devel


Download : https://tomcat.apache.org/download-connectors.cgi

 

$ cd /usr/local/src
$ wget https://mirror.navercorp.com/apache/tomcat/tomcat-connectors/jk/tomcat-connectors-1.2.48-src.tar.gz
$ tar zxvf tomcat-connectors-1.2.48-src.tar.gz
$ cd tomcat-connectors-1.2.48-src/native/
$ ./configure --with-apxs=/usr/bin/apxs
$ make
$ make install


서버의 apxs 경로 확인 후 올바르게 입력

 

 

3. mod_jk 설정

 

apache 버전마다 설정은 조금씩 다르니 httpd.conf 파일 참고.

 

$ vi /etc/httpd/conf.modules.d/00-jk.conf
LoadModule jk_module modules/mod_jk.so

 

$ vi /etc/httpd/conf.d/mod_jk.conf
<IfModule jk_module>
  JkWorkersFile conf.d/workers.properties
  JkLogFile logs/mod_jk.log
  JkLogLevel debug
  JkShmFile run/mod_jk.shm
  JkMountFile conf.d/uriworkermap.properties
</IfModule>

 

 

4. workers.properties 추가

3개의 Tomcat 인스턴스가 있다고 가정하고 각 인스턴스의 이름과 포트 설정.

 

$ vi /etc/httpd/conf.d/workers.properties
worker.list=tomcat1, tomcat2, tomcat3

worker.tomcat1.type=ajp13
worker.tomcat1.port=8109
worker.tomcat1.host=localhost

worker.tomcat2.type=ajp13
worker.tomcat2.port=8209
worker.tomcat2.host=localhost

worker.tomcat3.type=ajp13
worker.tomcat3.port=8309
worker.tomcat3.host=localhost



5. uriworkermap.properties

 

uri 에 매칭되는 workers.properties 의 worker 인스턴스로 ajp 통신. 해당하지 않는 uri 는 apache 디렉토리에서 매칭.

/=tomcat1
/instance2/*=tomcat2
/instance3/*=tomcat3



6. 톰캣 웹사이트 고양이 복사

 

$ mkdir -p /app/tomcat/instance2/webapps/ROOT/instance2
$ mkdir -p /app/tomcat/instance3/webapps/ROOT/instance3
$ cp /app/tomcat/instance1/webapps/ROOT/*.* /app/tomcat/instance2/webapps/ROOT/instance2
$ cp /app/tomcat/instance1/webapps/ROOT/*.* /app/tomcat/instance2/webapps/ROOT/instance3

 

 

7. SELinux 에 AJP 포트 추가

 

SELinux 정책에 의해 AJP 연결이 추가로 필요할 경우, 해당 IP 를 추가한다.
(/etc/selinux/config 파일에 SELINUX 설정을 변경하는 것은 추천하지 않는다.)

 

# semanage port -a -t http_port_t -p tcp 8109
# semanage port -a -t http_port_t -p tcp 8209
# semanage port -a -t http_port_t -p tcp 8309
# semanage port -l | grep http_port_t
http_port_t        tcp      8309, 8209, 8109, 80, 81, 443, 488, 8008, 8009, 8443, 9000

 

semanage 명령어가 없을 경우, policycoreutils-python 설치

 

# yum install policycoreutils-python

 

 

8. Web Server / WAS 재구동 후 연동 확인

 

http://serverIP
http://serverIP/instance2/
http://serverIP/instance3/

 


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

 

Tomcat 에서 여러 인스턴스를 관리하는 방법이 있다. CATALINA_HOME 디렉토리에서 필요한 부분만 복제하고 약간의 설정을 수정하여 인스턴스들을 구성할 수 있다. server.xml 파일 하나에 여러 호스트 정보를 등록하여 관리할 수도 있지만 이 경우 Tomcat 을 재구동하면 모든 서비스들이 재구동되는 단점이 있으므로 그다지 추천하지는 않는다.

 

[CATALINA_HOME]

  • Tomcat Engine 디렉토리 : bin, lib
  • Tomcat Instance 디렉토리 : conf(설정), logs(로그), webapps(소스), work(jsp구동), temp(임시)

 

위 내용들 중  Instance 디렉토리를 아래의 절차를 거쳐 별도로 구성해 주면 된다.(Tomcat 설치 생략)

 

  1. 필요한 만큼의 Tomcat Instance 디렉토리를 생성한다.
  2. CATALINA_HOME 으로부터 필요 디렉토리를 복제한다.(conf, webapps)
  3. server.xml 에서 port 등 환경을 변경한다.
  4. 인스턴스 실행/중지 스크립트를 만들고 실행한다.
  5. 방화벽에서 해당 port 를 추가한다.

 

테스트 환경 : CentOS 7 / Tomcat 8.5
테스트 목표 : 서버 ip 에 특정 포트들에 연결되는 여러 인스턴스 구동

 

 

1. Instance 디렉토리 생성

 

# mkdir -p /app/tomcat
# chown -R tomcat:tomcat /app/tomcat
# su - tomcat
$ cd /app/tomcat
$ mkdir -p instance1/logs

 

 

2. CATALINA_HOME 에서 디렉토리 복제

 

$ cp -a /etc/tomcat8/conf instance1
$ cp -a /etc/tomcat8/webapps instance1

 

 

3. server.xml 설정 변경

 

$ vi instance1/conf/server.xml

$ vi instance1/conf/server.xml

<Server port="8005" shutdown="SHUTDOWN">

  <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

 

여기에 shutdown port 와 http 서비스 port / https port 를 바꿔준다. 인스턴스가 3개 라면 8005/8105/8205, 8080/8180/8280, 8443/8444/8445 처럼 포트가 겹치지 않고 기억하기 쉽도록 구성하면 된다.

 

 

4. 구동 스크립트 생성

 

$ vi instance1/startup.sh

#!/bin/sh
export CATALINA_HOME=/etc/tomcat8
export CATALINA_BASE=/app/tomcat/instance1
$CATALINA_HOME/bin/startup.sh

 

$ vi instance1/startup.sh

#!/bin/sh
export CATALINA_HOME=/etc/tomcat8
export CATALINA_BASE=/app/tomcat/instance1
$CATALINA_HOME/bin/shutdown.sh

 

$ chmod u+x startup.sh
$ chmod u+x shutdown.sh

 

이렇게 설정하면 Tomcat 설치 디렉토리에서는 구동 스크립트만 빌려 각각의 인스턴스를 구동할 수 있게 된다. 구성된 instance1 디렉토리를 필요한 만큼 복제한다.

 

$ cp -a instance1 instance2
$ cp -a instance1 instance3

 

복제 후에는 이미 진행했던 3,4 번 단계의 각 인스턴스 설정(server.xml, startup.sh, shutdown.sh)을 변경해 준다.

 

 

5. 방화벽 해당 port 추가

 

# firewall-cmd --permanent --zone=public --add-port=8080/tcp
# firewall-cmd --permanent --zone=public --add-port=8180/tcp
# firewall-cmd --permanent --zone=public --add-port=8280/tcp
# firewall-cmd --permanent --zone=public --add-port=8443-8445/tcp
# firewall-cmd --reload

 

 

6. 각 인스턴스 구동 후 확인

 

$ /app/tomcat/instance1/startup.sh
$ /app/tomcat/instance2/startup.sh
$ /app/tomcat/instance3/startup.sh

 

http://serverIP:instance1port
http://serverIP:instance2port
http://serverIP:instance3port


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

NGINX vs MPM-PREFORK vs MPM-EVENT


Ubuntu 14.04 에서 apache 2.4 MPM prefork 를 사용중이다.

prefork 방식은 안정적이고 다른 소프트웨어와 호환성이 좋다고 알려져 있다.

동시 접속에 대해서는 쓰레드 방식의 worker / event / nginx 가 좋다고 알려져 있다.

그리고 나는 이것들이 실제 지금 우리 서버에도 해당되는지 테스트를 해봤다.

더불어 현재 설치된 prefork 방식의 한계도 알아보려고 한다.

현재 서버는 AWS r1.large 이다.



Prefork setting


# vi /etc/apache2/mods-enabled/mpm_prefork.conf
<IfModule mpm_prefork_module>
        StartServers              5
        MinSpareServers           5
        MaxSpareServers          10
        MaxRequestWorkers       150
        MaxConnectionsPerChild    0
</IfModule>
cs


최초 서버 시작시 프로세스는 5개로 시작하고, 여분의 프로세스 범위는 5~10 이고 요청을 처리할 수 있는 최대 프로세스 수는 150 개로 설정되어 있다.

하나의 프로세스당 하나의 요청을 받으니까 150개의 요청을 한번에 받고나면 150개가 클라이언트에 응답을 돌려줄 때까지는 더 이상의 요청을 받을 수 없다.

응답을 빨리 한 프로세스는 또 다른 요청을 받을 수 있을 것이고... 그것은 페이지의 용량 등 여러가지 리소스에 따라 달라질 것이다.


프로세스 확인


웹서버를 시작하고 나서 apache2 프로세스를 검색하면 


18625 ?        Ss     0:01 /usr/sbin/apache2 -k start
18630 ?        S      0:01 /usr/sbin/apache2 -k start
18642 ?        S      0:01 /usr/sbin/apache2 -k start
18652 ?        S      0:01 /usr/sbin/apache2 -k start
18673 ?        S      0:00 /usr/sbin/apache2 -k start
18711 ?        S      0:00 /usr/sbin/apache2 -k start
cs


부모 프로세스인 Ss 를 제외하면 프로세스가 5개 맞다. 



Prefork 과부하 테스트


Request page size : 52kb

Number of Threads : 최대 500

Ramp-Up Period : 1

Loop Count : 1


웹 서비스 성능 테스트 툴은 JMeter 를 사용하였다. (Apache Bench 도 결과적으로는 거의 흡사했다.)

테스트 PC 의 CPU 가 100% 가 되면 요청 Thread 가 동시에 전달될 수 없으므로, 요청 Thread(동시접속)는 500 정도까지 테스트 해보았다.

요청 페이지는 DB 연결도 필요하고 CDN 으로부터 적지 않은 이미지들도 불러오는 일반 쇼핑몰 메인 페이지 수준의 페이지이다.


Thread 1~10 은 응답속도가 0.4 초 나왔다. (전혀 문제 없음)

Thread 20 은 응답속도가 0.4~0.8 초 나왔다. 평균 0.6 (거의 문제 없음)

Thread 30 은 응답속도가 0.4~1.4 초 나왔다. 평균 1.0 (이정도는 문제 없음)

Thread 40 은 응답속도가 0.4~3.0 초 나왔다. 평균 1.6 (벌써 이러면 좀 걱정 됨)

Thread 50 은 응답속도가 0.4~3.0 초 나왔다. 평균 1.9 (최대 응답 속도는 이전과 동일)

Thread 60 은 응답속도가 0.6~3.9 초 나왔다. 평균 2.4 (벌어지기 시작함)

Thread 70 은 응답속도가 0.6~4.7 초 나왔다. 평균 2.8 (...)

Thread 80 은 응답속도가 0.6~5.8 초 나왔다. 평균 3.3

Thread 90 은 응답속도가 0.9~6.4 초 나왔다. 평균 3.9

Thread 100 은 응답속도가 0.8~7.4 초 나왔다. 평균 4.4

Thread 110 은 응답속도가 0.5~7.9 초 나왔다. 평균 4.6

Thread 120 은 응답속도가 0.5~8.9 초 나왔다. 평균 5.2

Thread 130 은 응답속도가 0.5~9.9 초 나왔다. 평균 5.8

Thread 140 은 응답속도가 0.6~10.4 초 나왔다. 평균 6.3

Thread 150 은 응답속도가 0.6~11.2 초 나왔다. 평균 6.9 


--(MaxRequestWorkers 설정값이 150 이라서 그런건지 뭔지 여기까지는 에러가 없다.


Thread 160 은 응답속도가 0.6~12.2 초 나왔다. 평균 7.2

Thread 200 은 응답속도가 0.9~15.6 초 나왔다. 평균 9.3

Thread 250 은 응답속도가 0.9~19.6 초 나왔다. 평균 11.4

Thread 300 은 응답속도가 0.6~22.8 초 나왔다. 평균 13.6

Thread 350 은 응답속도가 0.8~26.2 초 나왔다. 평균 15.4 (error 5.14%)

Thread 400 은 응답속도가 0.6~29.0 초 나왔다. 평균 16.9 (error 8.50%)

Thread 500 은 응답속도가 5.4~24.2 초 나왔다. 평균 17.5 (error 35.8%)


각 테스트는 프로세스가 안정화 되고나서 테스트를 하였다.

MaxRequestWorkers 설정 값이 150 인 상태에서 52kb 짜리 테스트 페이지는 동시 요청을 300 개 정도까지는 에러 없이 응답하였다.

발생한 에러는 콘솔에 툴 에러로 나왔는데 어찌됐든 응답 받지 못했으니 대충 에러로 인식.

RAM 사용량은 thread 500 요청시 8GB 중 apahce 에서 최대 1GB 정도만을 사용했다. CPU 도 25% 정도까지만 올라갔다. (서버 리소스는 완전 널널하다는...)

사실 3초 이상 브라우저의 로딩 화면을 바라보고 있는 사람은 거의 없다.

최대 3초 까지 방문 유저가 참아 준다고 치면 현재 상태에서의 동접은 50 정도까지가 안정적인 것으로 보인다.

매우 실망스러운 수치이다.

성능 테스트를 직접 해본것은 처음이였지만 내가 알고 있던 성능 테스트 결과와는 사뭇 달랐다.

이때까지만 해도 일단 페이지 자체가 가볍지 않고, 튜닝도 전혀 하지 않은 기본 설정 상태라서 그럴것이라고 생각했다.


그렇다면 MaxRequestWorkers 값을 늘리면 응답 속도가 늘어날까? (150->256)


Thread 50 은 응답속도가 0.7~3.2 초 나왔다. 평균 2.0 (비슷)

Thread 80 은 응답속도가 0.8~6.0 초 나왔다. 평균 3.4 (비슷)

Thread 100 은 응답속도가 0.9~7.5 초 나왔다. 평균 4.3 (비슷)

Thread 120 은 응답속도가 0.9~8.9 초 나왔다. 평균 5.0 (비슷)

Thread 150 은 응답속도가 1.0~11.4 초 나왔다. 평균 6.6 (비슷)

Thread 200 은 응답속도가 0.8~15.0 초 나왔다. 평균 8.5 (비슷)

Thread 300 은 응답속도가 0.9~22.5 초 나왔다. 평균 13.3 (비슷)

Thread 350 은 응답속도가 0.9~26.1 초 나왔다. 평균 15.8 (error 11.11%)


프로세스를 150 에서 256 으로 올려도 속도면에서는 거의 차이가 없었고 에러도 동일한 구간에서 발생하기 시작했다.

그렇다면 현재 상황에서는 프로세스 수를 1024 정도로 올리더라도 응답속도나 에러는 동일할 것으로 판단되었다.

그래도 확실하게 테스트.


MaxRequestWorkers 구성은 ServerLimit 에서 지정한 값보다 클 수 없는데, serverLimit 의 기본값은 256 이다.

MaxRequestWorkers 를 256 보다 크게 설정하려면 ServerLimit 값을 256보다 크게 설정해야 한다.

ServerLimit 는 여분의 메모리에 할당되므로 이 값을 너무 크게 설정하면 시스템이나 apache 가 불안정해 질 수 있다고 한다.

ServerLimit 는 200000 까지 설정할 수 있으며, 이 보다 더 큰 값을 적용시키려면 MPM 소스 파일에 MAX_SERVER_LIMIT 값을 수정하고 apache 를 재컴파일해야 한다.


MaxRequestWorkers 256->1024


<IfModule mpm_prefork_module>
        ServerLimit            1024
        StartServers              5
        MinSpareServers           5
        MaxSpareServers          10
        MaxRequestWorkers      1024
        MaxConnectionsPerChild    0
</IfModule>
cs


Thread 50 은 응답속도가 0.5~3.4 초 나왔다. 평균 2.1 (비슷)

Thread 100 은 응답속도가 0.9~7.7 초 나왔다. 평균 4.4 (비슷)

Thread 200 은 응답속도가 0.9~15.7 초 나왔다. 평균 9.0 (비슷)

Thread 300 은 응답속도가 1.0~23.5 초 나왔다. 평균 13.6 (비슷)

Thread 350 은 응답속도가 0.9~25.3 초 나왔다. 평균 15.3 (error 6.00%)


달라진게 없다. 하하~ ...prefork...

포기할 수 없다. 마지막으로 1024->100000 까지 올려봤다.


Thread 350 은 응답속도가 1.7~26.6 초 나왔다. 평균 16.0 (error 1.43%)


확실히 알게 되었다. prefork 튜닝은 다 부질 없음을...ㅋ

어짜피 첫 페이지에 대한 동시접속만 알아보려는 것이므로 Timeout, KeepAlive 등의 테스트는 하지 않았다.



Multi threads


NGINX vs MPM-WORKER vs MPM-EVENT


프로세스 방식의 mpm-prefork, 멀티 스레드 방식의 nginx / mpm-worker / mpm-event.

prefork 의 실망감을 감추지 못한채 큰 기대감을 갖고 위 3가지에 대해 prefork 와 동일하게 테스트 해보았다.

prefork 와 동일한 환경에서의 결과는...


...

...

...

...

...


따로 적기도 짜증날 정도로 prefork / nginx / mpm-worker / mpm-event 의 결과는 비슷했다. 스레드 수를 늘려도 마찬가지.

순간 네트워크의 속도가 약간씩 영향을 주는 것을 감안할 때 무엇이 더 좋다고 딱히 말할 수 없을 정도로 큰 차이가 없었다.

또한 AWS 에서 가장 낮은 사양의 t2.micro 에서도 동일했다. 하하.

(phpinfo 정도의 가벼운 페이지는 모두 1000 개의 동시접속을 1,2 초 내에 처리했다.)



나의 결론은 이렇다.


1. Apache 를 쓰던 Nginx 를 쓰던 속도나 처리 상에 큰 속도 차이는 없다.

2. 웹서버의 사양도 속도에 큰 차이를 보이지 않는다. (서버 사양을 늘리느니 서버를 한 대 더 추가하는게 나을듯...)

3. 튜닝한다고 프로세스, 쓰레드 수를 늘려도 처리 속도는 차이가 없다.


난 결국 이미 깔려 있는, 그리고 이 중 가장 안정적이라는 prefork 를 유지하기로 마음 먹었다.


끝!



WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

apr_sockaddr_info_get()

Daily/Prog 2013. 11. 20. 12:40

httpd: apr_sockaddr_info_get() failed for web.oops4u.com
httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName

 

요청 접수. apache 데몬 실행할 때 이런 오류가 나온다고...

 

건드린 것도 없어 보이고, httpd.conf 파일에 ServerName 127.0.0.1 을 추가해주니 오류는 나타나지 않지만,
2차 도메인에는 접근하지 못하는 이 이상한 현상...
IP 로는 접근이 잘되고 도메인으로는 접근이 안되는 현상 발견.
DNS 문제라 확신하고 DNS 업체에 진상부렸는데 그님 왈,

 

"DNS는 이상이 없구요. 님 도메인이 만료됐셨네요..."

 

ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
남 일에 내 쪽이 팔려버린... 아, 웃프다...


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,