2016년 10월 18일 화요일

오라클 접속 안될 시 체크

오라클 클라이언트 설치는 당연한 거겠죠?

 

1.오라클 홈 위치 확인
#윈도우
echo %ORACLE_HOME%

#리눅스
echo $ORACLE_HOME

2.tnsnames.ora 내용 확인(위치 : %ORACLE_HOME%\network\admin\tnsnames.ora)


SERVER_NAME =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = mydomain.com)(PORT = 1521))
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ORCL)
)
)


3.tnsping 체크
tnsping alias
ex>tnsping SERVER_NAME

4. sqlplus로 실제 접속 테스트
sqlplus 아이디/패스워드@ALIAS
EX>sqlplus myid/pass@SERVER_NAME

5.tnsnames.ora 내용으로 sqlplus 테스트(tnsnames.ora 내용에서 alias를 뺀 나머지 부분만 한줄로 만들어서 테스트)
sqlplus myid/pass@"(DESCRIPTION =    (ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = mydomain.com)(PORT = 1521)) ) (C
ONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = ORCL) ) )"

MSSQL 에서 오라클로 LINKED SERVER 생성시 오류

MSSQL 에서 오라클로 LINKED SERVER 생성시 오류 발생
연결된 서버 "SERVER_NAME"에 대한 OLE DB 공급자 "OraOLEDB.Oracle"의 인스턴스를 만들 수 없습니다. (Microsoft SQL Server, 오류: 7302)  도움말을 보려면 다음을 클릭하십시오:

이 사이트에서 해결책 확인

오라클 클라이언트 설치 후 SQLSERVER 재시작 해야됨.;;

2016년 10월 12일 수요일

vpopmail(pop3) brute force 공격 차단

qmail vpopmail 을 쓰고 있다.

서버 점검 중 pop3로 접속시도를 하는 로그를 발견했다.

없는 아이디로 계속 시도하는 것과 계정은 있지만 패스워드를 계속 틀리게 입력하는 유형 2가지.
Oct 11 11:27:54 mail vpopmail[27836]: vchkpw-pop3: vpopmail user not found admin12@domain.com:109.104.203.62

Oct 11 15:02:11 mail vpopmail[15277]: vchkpw-pop3: password fail (pass: 'e603f6c507b3993651f0439553584c50') acount@domain.com:110.70.15.59

한두개가 아니라 같은 아이피가 계정만 바꿔서 계속 시도하고 있다.
fail2ban으로 vpopmail 차단을설정하면 좋은데, 실 운영서버라 fail2ban 설치하기가 쉽지 않다.

그래서 스크립트 작성.
#/bin/bash


help()
{
echo ""
echo "/var/log/maillog is default"
echo "iptable apply is not default"
echo "banCount 100 is default"
echo "-a : iptable applied"
echo "-f : maillog FILE PATH"
echo "-c : ban count"
echo ""
echo "Usae : $0 -a -c 100 -f /var/log/maillog "
exit 0
}


ignoreIPs=("222.222.222.222" "111.111.111.111")
maillog="/var/log/maillog"
banCount=100
fw=false


while getopts ac:f: opt
do
case $opt in
a)
fw=true
;;
c)
banCount=$OPTARG
;;
f)
maillog=$OPTARG
;;
*)
help
exit 0
;;
esac
done


banIPs=`grep -E 'user not found|password fail' ${maillog} | awk -F: '{print $NF}' | sort | uniq -dc | awk '{if ($1 > '"${banCount}"') print $NF}'`

for banIP in $banIPs
do
for ignoreIP in ${ignoreIPs[@]}
do
if [ $ignoreIP == $banIP ]
then
# echo "ignore IP: ${ignoreIP}"
# echo "ban IP : $banIP"
break
fi
done

echo "ban IP : $banIP ,whois : $(geoiplookup $banIP)"
if [ $fw = true ] ; then
iptables -A INPUT -s ${banIP}/24 -j DROP
fi

done


if [ $fw = true ] ; then
#remove duplicate iptables rules
#http://www.krazyworks.com/remove-duplicate-iptables-rules/
/sbin/service iptables save
/sbin/iptables-save | awk '!x[$0]++' > /tmp/iptables.conf
/sbin/iptables -F
/sbin/iptables-restore < /tmp/iptables.conf
/sbin/service iptables save
/sbin/service iptables restart
if [ -f /tmp/iptables.conf ] ; then /bin/rm -f /tmp/iptables.conf ; fi
fi


 

1. banCount 는 같은 IP가 해당 값이상일 경우만 가져온다.
실제사용자가 실패할 경우도 있기 때문에 100정도면 적당한 것 같다.

2. ignoreIPs는 차단하지 않을 IP를 적어준다.

3. iptable에 적용하는 데, 중복으로 계속 적용된다.
마지막 부분이 중복을 없애고 다시 설정하는 부분이다.

maillog 파일의 생성을 살펴보면 매일 오전 4시 마다 rotate 되고 있다
cron으로 4시 30분 부터 실행되게끔 걸어주면 되겠다.

2016년 10월 5일 수요일

catalina.out파일에서 system.out.print 내용 확인이 안될 때...

centos7 에서 yum 을 이용해 tomcat을 설치하고

'systemctl stop tomcat.service' 명령어를 이용하여 톰캣을 실행하였다.

catalina.out 파일에서 system.out.print 내용이 쌓이지 않는 것을 확인하였다.

catalina.$DATE.log 파일에도 역시 쌓이지 않는다.

/var/log/messages에 해당 내용이 쌓인다.

명령어는 아래와 같이 사용하면 된다.
journalctl -u tomcat -f
or
tail -f /var/log/messages

참조1
참조2

2016년 9월 29일 목요일

vpopmail 설치시 에러

문경윤(디지문)님이 제작한 스크립트로 설치 중 vpopmail 설치 도중에러 발생.

환경은

centos 6.8 32bit 이며 mysql은

yum install mysql mysql-server

를 통해 'mysql  5.1.73'를 설치



에러 1.

configure: error: Unable to find your MySQL inc dir, specify --enable-incdir.

해결.
yum -y install mysql-devel



에러2.

gcc -I. -I/var/lib/mysql/ -I. -I. -I. -fPIC -g -O2 -Wall -c -o libvpopmail_a-vauth.o `test -f 'vauth.c' || echo './'`vauth.c
vauth.c:33:19: error: mysql.h: 그런 파일이나 디렉터리가 없습니다

해결.

mysql.h 파일은 mysql-devel을 설치하면 만들어지는 데 find 명령으로 찾아보니 그 위치가 /var/user/include/mysql 이다.
[root@localhost src]# find / -name mysql.h
/usr/include/mysql/mysql.h

근데 실제 mysqld은 /var/lib/mysql에 설치되어 있으니 거기서 mysql.h를 찾고 있다. 당연히 없지. 아래의 옵션으로 lib위치를 추가 해 주면 된다.

configure 옵션에 libdir=/var/user/include/mysql 추가

2016년 9월 28일 수요일

centos 7에서 변경 된 것 30가지.

centos 7이 되면서 기존에 사용하던 명령어가 없어져서 난감한 경우가 참 많다.

꽤 많은 부분이 바뀐 것 같다. 그래서 찾아 본 링크

영문임.. OTL

2016년 9월 5일 월요일

네이버 로그인 ASP 버젼 클래스

asp 사이트에서 네이버 로그인 사용 할 일이 생겨서 만들었다.

 

NaverOAuth.asp
<!--#include virtual="/lgdacom/md5.asp" -->
<!--#include virtual="/Class/json2.asp"-->
<%
Class clsNaverOAuth

Private Sub Class_Initialize()
End Sub

private m_clientId
private m_clientSecret
private m_redirectUrl
private m_state
private m_session
private m_code '로그인 인증 요청 API 호출에 성공하고 리턴받은 인증코드값 (authorization code)
private m_refreshToken '갱신 때 필수 - 네이버 사용자 인증에 성공하고 발급받은 갱신 토큰(refresh token)
private m_accessToken '삭제 때 필수 - 기 발급받은 접근 토큰으로 URL 인코딩을 적용한 값을 사용


Public Property Get clientId()
clientId = m_clientId
End Property

Public Property Let clientId(value)
m_clientId = value
End Property


Public Property Get clientSecret()
clientSecret = m_clientSecret
End Property

Public Property Let clientSecret(value)
m_clientSecret = value
End Property


Public Property Get redirectUrl()
redirectUrl = m_redirectUrl
End Property

Public Property Let redirectUrl(value)
m_redirectUrl = value
End Property


Public Property Get state()
state = m_state
End Property

Public Property Let state(value)
m_state = value
End Property


Public Property Get session()
session = m_session
End Property

Public Property Let session(value)
m_session = value
End Property


Public Property Get refreshToken()
refreshToken = m_refreshToken
End Property

Public Property Let refreshToken(value)
m_refreshToken = value
End Property


Public Property Get accessToken()
accessToken = m_accessToken
End Property

Public Property Let accessToken(value)
m_accessToken = value
End Property


Public Property Get code()
code = m_code
End Property

Public Property Let code(value)
m_code = value
End Property

Public Property Get generate_state
Dim rand, mt, state,returnVal
Randomize
rand = Int((999999 * Rnd) + 111111)
mt = Timer
generate_state = md5( mt & rand )
End Property

Public Property Get authQueryString()
authQueryString = "response_type=code"
authQueryString = authQueryString + "&client_id=" + m_clientId
authQueryString = authQueryString + "&redirect_uri=" + Server.URLEncode(m_redirectUrl)
authQueryString = authQueryString + "&state=" + Server.URLEncode(m_state)
End Property

Public Property Get tokenAuthQueryString()
tokenAuthQueryString = "client_id=" + m_clientId
tokenAuthQueryString = tokenAuthQueryString + "&client_secret=" + m_clientSecret
tokenAuthQueryString = tokenAuthQueryString + "&grant_type=authorization_code"
tokenAuthQueryString = tokenAuthQueryString + "&state=" + m_state '발급시
tokenAuthQueryString = tokenAuthQueryString + "&code=" + m_code '발급시
End Property

Public Property Get tokenRefreshQueryString()
tokenRefreshQueryString = "client_id=" + m_clientId
tokenRefreshQueryString = tokenRefreshQueryString + "&client_secret=" + m_clientSecret
tokenRefreshQueryString = tokenRefreshQueryString + "&grant_type=refresh_token"
tokenRefreshQueryString = tokenRefreshQueryString + "&refresh_token=" + m_refreshToken '갱신시
End Property

Public Property Get tokenDeleteQueryString()
tokenDeleteQueryString = "client_id=" + m_clientId
tokenDeleteQueryString = tokenDeleteQueryString + "&client_secret=" + m_clientSecret
tokenDeleteQueryString = tokenDeleteQueryString + "&grant_type=delete"
tokenDeleteQueryString = tokenDeleteQueryString + "&access_token=" + m_accessToken '삭제시
tokenDeleteQueryString = tokenDeleteQueryString + "&service_provider=NAVER" '삭제시
End Property

Public Function httpRequest(url, AuthTkn)
Dim returnDic : Set returnDic = Server.CreateObject("Scripting.Dictionary")
Dim objXMLHTTP : Set objXMLHTTP = server.CreateObject("MSXML2.ServerXMLHTTP")
objXMLHTTP.setOption 2,13056 'ignore SSL errors
objXMLHTTP.Open "POST", url, false
If AuthTkn = "" Then
objXMLHTTP.setRequestHeader "Content-Type", "application/json;charset=UTF-8"
Else
objXMLHTTP.setRequestHeader "Content-Type", "application/xml"
objXMLHTTP.setRequestHeader "Authorization", AuthTkn
End If
objXMLHTTP.Send

If objXMLHTTP.status = 200 Then
'response.write(objXMLHTTP.responseText)
'response.end
Dim jsonstring : jsonstring = objXMLHTTP.responseText
Dim Info : set Info = JSON.parse(join(array(jsonstring)))
Dim key : for each key in Info.enumerate()
returnDic.Add key, Info.get(key)
next
Else
'에러처리
returnDic.Add "error", "status is not 200"
End if

Set httpRequest = returnDic
End Function
End Class

%>

인클루드 파일 설명
md5.asp
stat 값을 생성할 때, asp 자체적으로는 md5 기능이 없어서 추가 했다.
네이버로그인 예제에 해당 기능을 사용하는 데 asp 는 그런 기능이 없다.

해당 사이트가 기존에 사용하고 있는 부분이여서
넣긴 했는데, md5 기능을 빼고 랜덤 함수만 사용하여도
크게 문제는 없을 것 같긴하다.

꼭 사용하려면 asp md5로 검색하면 역시 소스가 잘 나오기 때문에
추가하는데는 어렵지 않을 것이다.

 

json2.asp
네이버 리턴값을 json 으로 주기 때문에 넣어야 한다.
역시 asp 자체적으로 json 파싱기능이 없기 때문이다.

 

사용법
<%@Language="VbScript"%>

<!--#include virtual="/Class/NaverOAuth.asp"-->
<%
Dim NAVER_CLIENT_ID : NAVER_CLIENT_ID = "네이버클라이언트ID"
Dim NAVER_SECRET_KEY : NAVER_SECRET_KEY = "네이버비밀키"
Dim NAVER_REDIRECT_PC_URL : NAVER_REDIRECT_PC_URL = "http://mysite.com/oauth/naver/callback.asp"
Dim NAVER_REDIRECT_MOB_URL : NAVER_REDIRECT_MOB_URL = "http://m.mysite.com/naverLogin/callback.asp"
Dim NAVER_OAUTH_AUTHORIZE_URL : NAVER_OAUTH_AUTHORIZE_URL = "https://nid.naver.com/oauth2.0/authorize"
Dim NAVER_OAUTH_TOKEN_URL : NAVER_OAUTH_TOKEN_URL = "https://nid.naver.com/oauth2.0/token"
Dim NAVER_GET_USER_INFO_URL : NAVER_GET_USER_INFO_URL = "https://openapi.naver.com/v1/nid/me"


Dim clsOAuth : Set clsOAuth = new clsNaverOAuth

Session("NAVER_STATE") = clsOAuth.generate_state
clsOAuth.clientId = NAVER_CLIENT_ID
clsOAuth.state = Session("NAVER_STATE")
clsOAuth.redirectUrl = NAVER_REDIRECT_PC_URL
Dim queryString : queryString = clsOAuth.authQueryString

Response.redirect NAVER_OAUTH_AUTHORIZE_URL & "?" & queryString


%>

인클루드 파일 설명
첫번째 소스 내용을 /Class/NaverOAuth.asp 위치에 저장한 것을 불러오는 부분

 

callback.asp
<%@Language="VbScript"%>
<!--#include virtual="/Class/NaverOAuth.asp"-->

<%
Dim NAVER_CLIENT_ID : NAVER_CLIENT_ID = "네이버클라이언트ID"
Dim NAVER_SECRET_KEY : NAVER_SECRET_KEY = "네이버비밀키"
Dim NAVER_REDIRECT_PC_URL : NAVER_REDIRECT_PC_URL = "http://mysite.com/oauth/naver/callback.asp"
Dim NAVER_REDIRECT_MOB_URL : NAVER_REDIRECT_MOB_URL = "http://m.mysite.com/naverLogin/callback.asp"
Dim NAVER_OAUTH_AUTHORIZE_URL : NAVER_OAUTH_AUTHORIZE_URL = "https://nid.naver.com/oauth2.0/authorize"
Dim NAVER_OAUTH_TOKEN_URL : NAVER_OAUTH_TOKEN_URL = "https://nid.naver.com/oauth2.0/token"
Dim NAVER_GET_USER_INFO_URL : NAVER_GET_USER_INFO_URL = "https://openapi.naver.com/v1/nid/me"

Dim clsOAuth : Set clsOAuth = New clsNaverOAuth

Dim state : state = clsCom.CheckisTrim(Request.QueryString("state"))
Dim code : code = clsCom.CheckisTrim(Request.QueryString("code"))
Dim Error : Error = clsCom.CheckisTrim(Request.QueryString("error"))
Dim error_description : error_description = clsCom.CheckisTrim(Request.QueryString("error_description"))

If error <> "" Then
response.write("error")
response.write("<br>")
response.write(error)
response.write("<br>")
response.write(error_description)
response.end
End If

If Session("NAVER_STATE") <> state Then
response.write("인증 실패")
response.write("<br>")
response.write(Session("NAVER_STATE"))
response.write("<br>")
response.write(state)
response.write("<br>")
response.end
End If

'''===전송할 파라미터 지정
clsOAuth.clientId = NAVER_CLIENT_ID
clsOAuth.state = state
clsOAuth.clientSecret = NAVER_SECRET_KEY
clsOAuth.code = code
'Response.write( clsOAuth.tokenAuthQueryString & vbNewline)


Dim respInfo
Dim profileInfo
Dim authToken

'토큰 발급 요청
Set respInfo = clsOAuth.httpRequest(NAVER_OAUTH_TOKEN_URL &"?"& clsOAuth.tokenAuthQueryString,"")

If respInfo.Exists("error")=true Then
response.write("토큰 접속 요청 에러" & "<br>" )
response.write(respInfo.Item("error") & "<br>" )
Else
Session("NAVER_ACCESS_TOKEN") = respInfo.Item("access_token")
Session("NAVER_REFRESH_TOKEN") = respInfo.Item("refresh_token")
response.write(Session("NAVER_ACCESS_TOKEN") & "<br>" )
response.write(Session("NAVER_REFRESH_TOKEN") & "<br>" )
'프로필 정보 조회
authToken = respInfo.Item("token_type") &" "& respInfo.Item("access_token")
Set profileInfo = clsOAuth.httpRequest(NAVER_GET_USER_INFO_URL, authToken)

If profileInfo.Item("resultcode") = 00 Then
Dim key : for each key in profileInfo.Item("response").enumerate()
response.write(key & " : " & profileInfo.Item("response").get(key) & "<br>" )
next
Else
response.write("프로필 조회 요청 에러" & "<br>" )
response.write(profileInfo.Item("resultcode") & "<br>" )
response.write(profileInfo.Item("message") & "<br>" )
End If
End If



'Session 등록이 클래스 안에서 안됨.
'objXMLHTTP.Send 파라미터로 요청 하려고 했으나, 요청이 잘못 됐다는 에러메시지가 계속 나옴.
%>

 

ps. 네이버로그인을 적용하면서 알 게 된 건데, 해당 기능은 OAUTH 2.0 기능을 사용하고
이 프로토콜은 IETF 표준으로 네이버만 사용하는 기술이 아닌 것이다.
페이스북, 트위터, 구글등 OAUTH 2.0 기능으로 로그인 기능을 제공 하고 있다.

ps2. 개발하면서 이상하다고 생각한게 토큰 갱신,삭제 부분이다. 몇몇 샘플 코드를 봐도
토큰 요청만 개발 해 놓고, 갱신, 삭제 부분은 만들어 놓지도 않았다.

이론적으로는 토큰 요청후  일정시간(expires_in )이 지나면 기존의 토큰은 사라지고 토큰 갱신을 해야 한다는 건데, 그렇게 하지 않아도 토큰 요청을 하면 새로운 토큰을 넘겨준다. 그러면 토큰 갱신이 별 의미가 없어 보인다.

또 토큰 삭제 역시 매뉴얼에는 어플리케이션 연동을 해제 할 때라고 나와 있지만 정작 네이버설정의 '외부 사이트 연결관리' 부분에는 연동한 사이트가 그대로 남아있다.

그에 대한 해답은 여기에서 찾았다.

결론은 엑세스 토큰이 문제가 생겼거나, 보안 이슈를 최소화 하기 위해서 인것 같다.