티스토리 뷰

728x90
반응형

 포스팅은 Oracle / Tibero 접속세션을 구분하는 방법에 대한 고찰입니다.


본 가이드는 /dev/random 으로 인한 지연에 대해 설명하고 있습니다.

/dev/random 이란?

random 의 의미가 "임의의", "일정치 않는"의 뜻을 가진다는 것은 누구든지 알고 있을것이다. 가장 간단한 랜덤값의 예는 주사위가 던져질경우 나오는 눈의 수 가 될것이며, 던지는 사람이 아무 생각없이 던질경우 "임의의" 값이 나오게 될것이다.

이 "임의의" 값은 일상생활에서 자주 사용되며, 특히 "보안"을 필요로 하는곳에서 더욱 중요하게 다루어진다. 금고의 문을 열기 위한 6자리의 숫자를 조합한다고 했을때, 카드에서 현금서비스등을 서비스받기 위해 사용하는 4자리 숫자의 조합등 "임이의" 값이 사용되어야 할것이다. 흔히 이러한 숫자조합을 만들때 가장 문제시 되는게, "임의의" 값을 사용하지 않고 숫자조합을 만든다는 점이다. 자기 생일이라든지, 아는 사람의 전화번호등이 대표적인 예로, 이런 값들은 "임의의"값이 아니다. 임의의 값이 아니란 뜻은 유추가 가능함을 뜻하며, 유추가 가능하다는 것은 그만큼 헛점이 많아질수 있음을 뜻한다.

컴퓨팅 환경에서도 이러한 "임의의"값 을 선택할수 있어야 한다. 선택된 임의의 값은 여러가지 용도로 사용될것인데, 대표적으로 사용할수 있는게 사용자 확인을 위한 "password" 와 SSL 과 같은 라이브러리등에서 암호화및 복호화를 위한 key값등의 제작일 것이다.

이러한 "임의의"값들은 당연하지만 최대한 "임의의"값으로써, 가능한 유추될수 없는 값이 되어야 할것이다. 만약 우리가 "임의의"값 을 얻기 위한 어떤 함수를 만들었고, 이 함수를 통해서 1-9999 사이의 임의의 값을 얻어내려고 하는데, 함수를 사용했더니 5000 - 6000 사이의 값이 다른 값보다 특별히 많이 나온다면, 이 함수는 믿을수 없는 "결함이 있는" 함수가 될것이며, 이 함수를 사용하는 많은 프로그램은 보안 결함을 가지게 될것이다. 이상적으로 각각의 값이 선택될 확률은 모두 동일(1/값의범위)해야 할것이다.

/dev/random을 사용하는데 있어서 사소한(때에 따라서는 심각한) 문제가 하나 있는데, 장치의 노이즈를 수집해서 앤트로피 풀에 저장하고 이 값을 이용해서 랜덤값을 만들어 낸다는 특징 때문에 장치에 노이즈가 없을 때는 앤트로피 풀이 비어 버리고, 때문에 매우 오랜 시간동안 랜덤값이 발생하지 않을 수 있다는 점이다.

WAS(Weblogic, JBoss, Jeus 등) 을 사용하다가 startup 또는 Create Connection, getConnection 등의 작업을 수행할 때 갑자기 성능이 느려지는 경우가 있습니다. Log 를 보면 아무 작업을 하지 않는 상태에서 멈춰있는 것을 볼 수 있습니다.


/dev/random

   - entropy가 특정 조건까지 만들어져야지 난수 발생합니다.

   - 복잡한 암호화 수행으로 변조에 대한 어려움이있습니다.

/dev/urandom

   - entropy가 특정 조거까지 만들어지지 않더라도 난수 발생합니다.

   - random 보다는 보안이 약하지만, 성능이 빠다.

/dev/ramdom 이 느려질 수 있는 원인은 Server Box 의 경우 디바이스가 거의 없기 때문에 entropy 생성에 시간이 소요됩니다.

1. 개요

Oracle getConnection시 지연 또는 Connection reset 발생에 대한 조치방법을 알아봅니다.

일반적으로 연결에 실패하여 WaitTimeOutException 또는 SocketException이 발생되게 됩니다.

ERROR manager.SqlManager: Error executing statement: java.sql.SQLRecoverableException: IO Error: Connection reset

java.sql.SQLRecoverableException: IO Error: Connection reset

at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:498)

at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:553)

at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:254)

at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32)

at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:528)

at java.sql.DriverManager.getConnection(DriverManager.java:571)

at java.sql.DriverManager.getConnection(DriverManager.java:215)

at org.apache.sqoop.manager.SqlManager.makeConnection(SqlManager.java:904)

at org.apache.sqoop.manager.GenericJdbcManager.getConnection(GenericJdbcManager.java:52)

at org.apache.sqoop.manager.SqlManager.execute(SqlManager.java:763)

at org.apache.sqoop.manager.SqlManager.execute(SqlManager.java:786)

at org.apache.sqoop.manager.SqlManager.getColumnInfoForRawQuery(SqlManager.java:289)

at org.apache.sqoop.manager.SqlManager.getColumnTypesForRawQuery(SqlManager.java:260)

at org.apache.sqoop.manager.SqlManager.getColumnTypesForQuery(SqlManager.java:253)

at org.apache.sqoop.manager.ConnManager.getColumnTypes(ConnManager.java:336)

at org.apache.sqoop.orm.ClassWriter.getColumnTypes(ClassWriter.java:1858)

at org.apache.sqoop.orm.ClassWriter.generate(ClassWriter.java:1658)

at org.apache.sqoop.tool.CodeGenTool.generateORM(CodeGenTool.java:107)

at org.apache.sqoop.tool.ImportTool.importTable(ImportTool.java:488)

at org.apache.sqoop.tool.ImportTool.run(ImportTool.java:615)

at org.apache.sqoop.Sqoop.run(Sqoop.java:143)

at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:70)

at org.apache.sqoop.Sqoop.runSqoop(Sqoop.java:179)

at org.apache.sqoop.Sqoop.runTool(Sqoop.java:218)

at org.apache.sqoop.Sqoop.runTool(Sqoop.java:227)

at org.apache.sqoop.Sqoop.main(Sqoop.java:236)

Caused by: java.net.SocketException: Connection reset

at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:118)

at java.net.SocketOutputStream.write(SocketOutputStream.java:159)

at oracle.net.ns.DataPacket.send(DataPacket.java:210)

    

                                                                                                    

2. getConnection 지연 원인

- 11g JDBC 드라이버는 사용시 connect string을 암호화하기 위해서 /dev/random을 이용하여 난수를 생성하여 connect string을 암호화 하는데, /dev/random로 인하여 지연이 발생하는 경우가 있습니다.

 

3. /dev/random 인한 지연인지 확인하는 방법

- 아래와 같이 테스트소스로 getConnection 테스트시 connection 연결이 일정하지 않은 경우, /dev/random으로 인한 지연으로 판단 할 수 있습니다.

import java.sql.*;

public class DBConnTest {

 public static void main(String[] args) {

  Connection conn=null;

  try {

        Class.forName("oracle.jdbc.driver.OracleDriver");

        System.out.println("JDBC Driver Loading Success");

        long start = System.currentTimeMillis();

        conn=DriverManager.getConnection("jdbc:oracle:thin:@210.1.1.1:1521:ORA", "id", "passwd");

        System.out.println("Connected..");

        long stop = System.currentTimeMillis();

        System.out.println("connected Time" + (stop - start) + " ms.");

        conn.close();

  } catch (ClassNotFoundException cnfe) {

        System.out.println("Not Found Class.."+cnfe.getMessage());

  } catch(SQLException se){

        System.out.println(se.getMessage());

  } finally {

        if(conn != null)   try {conn.close();} catch (SQLException e) { e.printStackTrace();}

   }

 }

}

 

- 테스트 결과 getConnection시간이 일정하지 않음을 확인 할 수 있습니다.

컴파일 : javac -classpath ojdbc6.jar DBConnTest.java

수행 : java -classpath ojdbc6.jar:. DBConnTest

JDBC Driver Loading Success

Connected..

connected Time 141 ms.

JDBC Driver Loading Success

Connected..

connected Time 139 ms.

JDBC Driver Loading Success

Connected..

connected Time 2757 ms.

JDBC Driver Loading Success

Connected..

connected Time 4192 ms.

JDBC Driver Loading Success

Connected..

connected Time 7452 ms.

JDBC Driver Loading Success

Connected..

connected Time 2813 ms.

JDBC Driver Loading Success

Connected..

connected Time 5459 ms.

JDBC Driver Loading Success

Connected..

connected Time 6179 ms.

JDBC Driver Loading Success

Connected..

connected Time 2816 ms.

JDBC Driver Loading Success

Connected..

connected Time 8443 ms.

JDBC Driver Loading Success

Connected..

connected Time 3539 ms.

JDBC Driver Loading Success

 

4. /dev/random 지연 원인

- /dev/random은 장치의 노이즈(디스크 읽기, 네트워크 패킷, 마우스움직임, 키보드 입력 등)를 수집해서 entropy pool에 저장하고 이 값을 이용해서 난수를 만들기 때문에 보안에는 좋습니다.

하지만 entropy를 수집하는 시스템 이벤트를 기다려야 하기 때문에, 장치의 노이즈가 없을 때에는 entropy pool이 비어버리고, 매우 오랜 시간 난수가 발생하지 않을 수 있습니다.

이렇게 entropy가 부족한 경우, block되어 대기하게 되기 때문에 getConnection시 지연이 발생하거나, Connection reset이 발생하게 되는 것 입니다.

- /proc/sys/kernel/random/poolsize 파일로 entropy pool의 크기를 알 수 있고,

/proc/sys/kernel/random/entropy_avail 파일로 현재 entropy_count 값을 알 수 있습니다.

 

5. 조치 방법

- /dev/random이 아닌, /dev/urandom을 사용하도록 설정을 변경 합니다.

- /dev/urandom은 충분한 entropy가 없는 경우에도 현재 entropy pool 내의 데이터 만으로 난수를 생성하며 block되지 않습니다.

- 아래의 두가지 방법 중 한가지를 적용하면 됩니다.

a. $JAVA_HOME/jre/lib/security/java.security 수정

securerandom.source=file:/dev/urandom

=> securerandom.source=file:///dev/urandom

b. WAS 설정 추가

- $JEUS_HOME/config/`hostname`/JEUSMain.xml

- 컨테이너별 command-option에 -Djava.security.egd=file:///dev/urandom 추가

 

6. 옵션 적용하여 재 확인

- 테스트소스 수행 시 -Djava.security.egd=file:///dev/urandom 옵션을 주면 아래와 같이 일정한 시간으로 getConnection이 됨을 확인 할 수 있습니다.

수행 : java -Djava.security.egd=file:///dev/urandom -classpath ojdbc6.jar:. DBConnTest

JDBC Driver Loading Success

Connected..

connected Time 121 ms.

JDBC Driver Loading Success

Connected..

connected Time 123 ms.

JDBC Driver Loading Success

Connected..

connected Time 114 ms.

JDBC Driver Loading Success

Connected..

connected Time 117 ms.

JDBC Driver Loading Success

Connected..

connected Time 115 ms.

JDBC Driver Loading Success

Connected..

connected Time 118 ms.

JDBC Driver Loading Success

Connected..

connected Time 118 ms.

JDBC Driver Loading Success

Connected..

connected Time 114 ms.

JDBC Driver Loading Success

Connected..

connected Time 118 ms.

JDBC Driver Loading Success

Connected..

connected Time 115 ms.

JDBC Driver Loading Success

Connected..

connected Time 115 ms.

JDBC Driver Loading Success

Connected..

connected Time 115 ms.

JDBC Driver Loading Success

Connected..

connected Time 117 ms.

 

getConnection 시간이 눈에 띄게 좋아진 것을 볼수 있습니다.

고맙습니다.

728x90
반응형