회사에서 라이센스를 유지하려면 감사를 받아야하고 그 항목중에는 퇴사자 처리 규칙이 존재한다.

계정관리가 완전히 되면 상관이 없겠지만 혼자서 한국/외국 사무실과 인프라 관련 계정을 관리하다보니

직접 관리하기가 생각보다 어렵다. 각국의 인사팀에서 slack은 확실하게 관리해주고 있어서 slack 기준으로 퇴사자를 비교한다.

대부분 API를 제공해줘서 (github, aws, private cloud, apm monitoring tool) 문서를 보고 알아서 만들어다가 썼는데

 

Jenkins는 예외였다..

관리하려면 jenkins 사용자 목록을 가져와야 하고 그것과 관련한 API가 있긴한데

Script Console에서 Groovy script 문법을 이용해서 가져오는 방법이 있다.

다른 방법은 못 찾았다. 분명 더 편한 방법이 있을텐데...

 

개발, 스테이지 등.. 환경별로 다르게 jenkins를 사용하고 있고 여기에 각각의 계정이 존재한다.

(그룹계정을 사용하면 편한데 auditor 지적사항에 걸리면 안되서 사용 불가하다.)

 

외국 현지 부서의 인력이 드나드는 것은 공유가 안되서 알기가 어렵다. 거기에도 담당인력을 뽑아주면 되긴하지만.. 일단 혼자 하게 되었다.

 

 

Groovy script를 이용하는 방법이 있다.

stackoverflow.com/a/56558259

 

'Manage Jenkins' 를 클릭하고 좀 내려보면 'Script Console'이 있는데 그것을 이용한다.

 

 

curl을 이용해서 jenkins에 로그인 해서 Groovy script를 돌릴 수 있다.

참고로 명령어에 id와 key 정보가 있으니 내부망에서 안전하게 수행하는것을 권고한다. 

 

1. API token이 필요하다. 이 것은 내 계정의 Configure에서 만들 수 있고 적절하게 이름을 붙여준다.

curl 명령어

curl --user '계정:API_TOKEN' -XPOST https://jenkins.enqdeq.net/scriptText -d 'script=Hudson.instance.getSecurityRealm().getAllUsers().each%20{%20println%20it%20}'

사용한 옵션

  • --user의 ID:API_TOKEN 정보로 auth 획득
  • -XPOST를 이용해서 groovy script를 run 한다. (참고로 위의 url은 존재하지 않고 본인의 jenkins url을 사용한다)
  • -d 로 전달하려는 데이터 추가 (groovy script를 한줄로 적는데 space를 사용하면 "Illegal character SPACE=' '" 에러가 발생하기 때문에 url 인코딩 시킨 %20으로 대신한다.

명령어 결과는 실제로 jenkins에서 수행한것과 동일하게 보인다.

 

그 결과와 퇴사자 계정 비교해서 처리하도록 해두면 완료

간단하게 적어두긴했으나 웹에서 수동으로 Groovy script 돌리던것을 curl 명령어로 할 생각을 하기까지 1년정도 걸렸다.

 

 

 

안녕하세요 쿤드입니다. 🍀

 

가끔씩 보고 싶은 정보들을 모아 블로그에서 보고 싶을때 정보를 쫙 모아다가

Tistory의 OpenAPI를 이용해서 올리곤 했었습니다. (가끔이라서 수동으로 함)

 

오늘 오랜만에 좀 보려고 했는데

자꾸 400 Error가 발생하고 이유는 모르겠고.. 뒤져보니 response_type=code 방식을 이용해서 

하라고 하는 것을 보니 뭔가 변경된것 같았습니다.

 

Open API 사용하기 위한 App 등록이 선행되어야 하는데
이는 검색하면 많이 나와서 넘어갑니다.

 

자세히 Autoriztion Code 방식을 읽어보니 기존에 제가 인증받아서 사용하던 code에서 끝나는 것이 아니라

그 code를 가지고 token을 받아서 그 token을 이용해야 하는 것이 었습니다.

 

그래서 방법은 총 3단계 (기존엔 2단계)

  1. Tistory Login
  2. Authentication code 발급
  3. Access Token 발급

 

확인하는 방법은 2가지가 있습니다.

웹브라우저에서 해보거나, 뭐가 되었든 코드로 짜서 자동으로 하거나

우선은 수동으로 먼저 확인해봅니다. python3 코드는 이 페이지 하단에서 볼 수 있습니다.

 

웹브라우저에서 직접 해본다.

1번 과정 - https://www.tistory.com 로그인한다.

2번 과정 - Autentication Code 발급 받는다.

웹 브라우저에 입력할 내용

https://www.tistory.com/oauth/authorize?client_id=app의 ClientID&redirect_uri=리다이렉션 받을 URI&response_type=code  

 

예시(아래 것은 샘플이라 에러페이지 나옴, client_id에 임의의 값을 넣어서 되지 않음, redirection은 내 맘대로함)

https://www.tistory.com/oauth/authorize?client_id=d962867605b93asdfasdfasd6fb96f8cc27568b141c&redirect_uri=sfixer.tistory.com&response_type=code

 

 

 

3. Access Token을 발급 받는다.

웹 브라우저에 입력할 내용

www.tistory.com/oauth/access_token?client_id=나의 CLIENT_IDc&client_secret=나의 CLIENT_SECRET&redirect_uri=설정한 redirect uri &code=2번과정에서 받아온 code 정보&grant_type=authorization_code

 

예시 (샘플이라 아무정보나 들어있음, 본인것에 맞게 바꿔야함)

www.tistory.com/oauth/access_token?client_id=ddszxcvzxcv36fb96f8cc27568b141c&client_secret=d962867zxcvzxcvelkasjdflkjasldk51ca867454aac07d9b98bde63553ba3d8a93&redirect_uri=sfixer.tistory.com&code=a1175b123409821093saldjfklasdjflkasdjflke91c5a3dc8b4514268a4e3a066&grant_type=authorization_code

 

 

코드로 구현한다

 

위에 처럼 해도되지만 간단하게 파이썬 코드 몇줄로 3단계 동작을 수행하겠습니다. 

개인정보들은 환경변수에 등록해서 가져와서 썼기때문에 그 부분만 따로 (하드코딩이든 뭐든) 처리해주시면 동작합니다.

테스트까지는 해보았습니다.

물론 아래의 제가 한 코드보다 훨씬 더 간결하게 구현이 가능할 것입니다. 

이를 공유한 이유는 저 처럼 삽질하는 사람을 좀 돕고자 공유했습니다.

 

Python3.8.5을 사용했으며

사용했던 패키지 버전 정보입니다.

  • requests==2.24.0
  • selenium==3.141.0
#!/usr/bin/env python3
import os
import re
from requests import get
from selenium import webdriver
from selenium.webdriver.chrome.options import Options


# tistory에 로그인을 합니다.
def tistory_login():
    tistory_id = os.environ.get('TISTORY_ID')
    tistory_pw = os.environ.get('TISTORY_PW')
    chromedriver_path = os.environ.get('CHROMEDRIVER_PATH')
    chrome_options = Options()
    chrome_options.add_argument("--headless")  # chrome 띄워서 보려면 주석처리
    driver = webdriver.Chrome(chromedriver_path, options=chrome_options)
    driver.implicitly_wait(3)
    driver.get('https://www.tistory.com/auth/login?redirectUrl=http%3A%2F%2Fwww.tistory.com%2F')
    driver.find_element_by_name('loginId').send_keys(tistory_id)
    driver.find_element_by_name('password').send_keys(tistory_pw)
    driver.find_element_by_xpath('//*[@id="authForm"]/fieldset/button').click()
    return driver


# authentication code 정보를 가져옵니다.
def get_authentication_code(driver, client_id, redirect_url):
    req_url = 'https://www.tistory.com/oauth/authorize?client_id=%s&redirect_uri=%s&response_type=code&state=langoo' % (client_id, redirect_url)
    driver.get(req_url)
    driver.find_element_by_xpath('//*[@id="contents"]/div[4]/button[1]').click()
    redirect_url = driver.current_url
    temp = re.split('code=', redirect_url)
    code = re.split('&state=', temp[1])[0]
    return code


# http://www.tistory.com/guide/api/index
# access token 정보를 가져옵니다.
def get_access_token(code, client_id, client_secret, redirect_url):
    url = 'https://www.tistory.com/oauth/access_token?'
    payload = {'client_id': client_id,
               'client_secret': client_secret,
               'redirect_uri': redirect_url,
               'code': code,
               'grant_type': 'authorization_code'}
    res = get(url, params=payload)
    token = res.text.split('=')[1]
    return token


def main():
    client_id = os.environ.get('TISTORY_CLIENT_ID')
    client_secret = os.environ.get('TISTORY_CLIENT_SECRET')
    redirect_url = os.environ.get('TISTORY_REDIRECT')
    driver = tistory_login()
    code = get_authentication_code(driver, client_id, redirect_url)
    token = get_access_token(code, client_id, client_secret, redirect_url)
    print(token)


if __name__ == '__main__':
    main()

안녕하세요 쿤드입니다. 🍀

테넌트의 개념에 대해서 알아보려고 합니다.

 

테넌트(tenant): 클라우드 인프라/서비스 제공 방식

  • 싱글 테넌트: 1개 서버에 대해 1개 기업의 데이터, 어플리케이션만 제공
  • 멀티 테넌트: 다른 사용자들과 서버, 스토리지를 공유

싱글과 멀티의 차이는 하드웨어를 공유하는가 안 하는가의 차이입니다.

 

이해를 돕기위해 이미지를 같이 보면

독립적으로 구성이 될 수록 Single-Tenant에 가깝고

Multi-Tenant에 가까워 질수록 사용자가 모든 자원을 공유해서 사용합니다.

출처: http://publicstaticmain.blogspot.com/2016/05/multitenancy-with-spring-boot.html

 

멀티테넌시의 장점으로는 비용 절감 입니다. (출처: http://www.itworld.co.kr/news/101255)

그리고 관리상의 이점도 있습니다.

하드웨어 리소스를 효율적으로 사용할 수 있고, 

하드웨어에 설치된 software에 보안 patch를 하거나 upgrade 하는 경우에도 1곳만 신경써주면 되기때문입니다.


반대로 단점으로는

내부적으로는 각 사용자별로 isolate 시켜야하고, 한곳의 보안이 뚫리게 되면 모든 사용자들의 정보가 다 유출되기때문에 

이를 관리하기 위한 인력의 비용도 무시할 수는 없습니다.

안녕하세요 쿤드입니다. 🍀

RFC 793에 나와있는 상태도를 바탕으로 하나씩 따라가면서 확인하면 보입니다.

python2로 구현된 간단한 tcp client/server 코드와 함께 확인해보겠습니다.

 

* TCB: Transmission Control Block


 

ESTABLISHED까지는 1가지 경우인데
종료할때는 2가지 case로 나뉩니다. RFC793 Link

  • Normal Close(일반 종료): FIN-WAIT-1 ➡️ FIN-WAIT-2 ➡️ TIME-WAIT
  • Simultaneous close(동시 종료): FIN-WAIT-1 ➡️ CLOSING ➡️ TIME-WAIT
일반 종료 
- 어느 한쪽에서 종료하기 위해 FIN을 날린 경우
동시 종료
- Clinet, Server 양쪽에서 동시에 FIN을 날린 경우

Python Code로 테스트 (Code link)

Server Client

 

Server쪽에서 일반 종료인 경우 netstat으로 확인해서 보았습니다.

 

Server에서 socket() 열고, bind()하고 listen() 함수 호출해서 Listening을 하면

  tcp        0      0 0.0.0.0:9999            0.0.0.0:*               LISTEN      8268/python          off (0.00/0/0)

 

Client에서

connect() 호출하면
  tcp        0      0 SERVER_IP:9999      CLIENT_IP:36391     ESTABLISHED 8268/python          off (0.00/0/0)

 

send(), recv() 호출 이후 종료
  tcp        0      1 SERVER_IP:9999      CLIENT_IP:36391     FIN_WAIT1   -                    on (0.17/0/0)
  tcp        0      0 SERVER_IP:9999      CLIENT_IP:36391     FIN_WAIT2   -                    timewait (8.99/0/0)
  tcp        0      0 SERVER_IP:9999      CLIENT_IP:36391     FIN_WAIT2   -                    timewait (7.97/0/0)
  tcp        0      0 SERVER_IP:9999      CLIENT_IP:36391     TIME_WAIT   -                    timewait (59.90/0/0)
  tcp        0      0 SERVER_IP:9999      CLIENT_IP:36391     TIME_WAIT   -                    timewait (58.88/0/0)
  tcp        0      0 SERVER_IP:9999      CLIENT_IP:36391     TIME_WAIT   -                    timewait (57.86/0/0)


CLOSE_WAIT 상태는 상태도만 봤을때 이해가 잘 안가서 Server/Receiver 쪽에서 억지로 재현해보았습니다.

  • Client/Sender에서 ESTABLISHED 이후에 data를 보냄
  • Server/Receiver에서 'ACK!' 라고 응답 (60sec 대기)
  • Client/Sender에서 data를 보냄
  • Server/Receiver는 여저히 sleep으로 대기상태
# 서버쪽 응답하는 thread 코드
def handle_client_connection(client_socket):
    while True:
        request = client_socket.recv(1024)
        print 'Received {}'.format(request)
        print 'send ack & sleep'
        try:
            client_socket.send('ACK!')
            time.sleep(60)  # <--- 여기서 막음 
        except socket.error as error:
            break
    client_socket.close()
  • 이때 Client/Sender는 응답을 못 받아서 대기중인 상태인데 강제로 종료 (Ctrl + C, KeyboardInterrupt)

 

이렇게 하는 경우 또 다른 client에서 붙고 마찬가지로 멈춰버린 상태에서 client process 강제 종료


tcp        0      0 0.0.0.0:9999            0.0.0.0:*               LISTEN      17043/python         off (0.00/0/0)
tcp       54      0 SERVER_IP:9999      CLIENT1_IP:39099     CLOSE_WAIT  17043/python         off (0.00/0/0)
tcp       54      0 SERVER_IP:9999      CLIENT2_IP:47657      CLOSE_WAIT  17043/python         off (0.00/0/0)

 

이 예시에서는 sleep 60으로 60s 지나면 해소가 되는데

Deadlock이라도 걸려서 저 상태가 계속해서 지속되면 결국엔 CLOSE_WAIT이 쌓여서 사용 가능한 PORT를 전부 사용하게 될테고

서버가 행업이 됩니다.

저 상태에서 Server side가 close를 호출하지 못하면 CLOSE_WAIT은 자동으로 사라지지도 않습니다.

 

이것이 실제 production 환경에서 발생한다면

dead lock 걸린 부분을 찾아서 소스 코드를 수정하기 전까지는 

시스템 엔지니어는 주기적으로 CLOSE_WAIT 개수를 체크해서 서버 프로세스를 재시작해주면서 버티는 방법밖에는 없어보입니다.

'기타' 카테고리의 다른 글

Python3를 이용한 Tistory Authentication Code 방식 인증 (2020.09.01 변경사항 반영)  (0) 2020.09.25
테넌트  (0) 2020.07.23
TCP Status 상태에 대해서  (1) 2020.07.15
TCP 통계수치 변화 (장애 상황)  (0) 2020.07.15
TCP 통계  (0) 2020.07.14
Kerberos Setup (KR)  (0) 2019.08.22
  1. 쿠즈몰 2020.07.17 22:34

     

안녕하세요 쿤드입니다. 🍀


엔지니어로 밥먹어 먹고 살고 있는데

TCP를 제대로 아는것이 없어서 하나씩 이해해보려고 하는중에 있습니다.

실제로 사용하는것의 값은 없애고 factor중에서 변화폭이 컸던 것들 위주로 간추려서 정리를 해보겠습니다.

 

물론 네트웍 트래픽만 봐도 장애라는것을 인지할 수는 있습니다.

평소 장애

 

TCP 통계 지표를 24개만 모아서 보고 있는데 (1분마다 이전과 현재의 증가한 차이 값을 수집해서 추이를 봄)

그중에 10개만 추려보았고 

그 중에서 다시 추려보니 ActiveOpens, PassiveOpens 추이만 봐도 장애 예측은 가능하겠네요..

 

당시 앞단에 있던 nginx에서 발생했던 error log (에러 해결 관련 nginx 설정 링크

upstream sent invalid chunked response while reading upstream, 

 

빨간선: ActiveOpens

파란선: PassiveOpens

평소 장애

큰 폭으로 감소했던 지표들을 요약하면

  • Nginx error 발생으로 신규 TCP 연결이 급격하게 감소 (나머지 지표는 그에 따른 영향으로 감소)

아... 그간 이 지표의 의미 해석을 미루고 미루고 미뤘는데 결과가 이렇게 허무하다니..

유입 고객이 늘어나서 터져나가는 장애를 겪어야 할텐데.. 코로나는 언제 지나가려나... 코로나가 간다고 손님이 늘긴하려나...

 

 

 

ActiveOpens

- TCP Client/Receiver (SYN을 보내고 SYN-SENT 상태가 된)

 

PassiveOpens

- TCP Server/Sender (SYN 받고 SYN-ACK 보내고 SYN-RCVD 상태가 된)

 

 

AttemptFails 

- TCP 연결이 SYN-SENT 상태 또는 SYN-RCVD 상태에서 CLOSED 상태로 곧 바로 전환된 횟수

- TCP 연결이 SYN-RCVD에서 LISTEN 상태로 바로 전환한 횟수

 

RetransSegs

- 재전송된 총 세그먼트 수(이전에 전송했던 하나 이상의 TCP 세그먼트를 포함하여 전송한 TCP 세그먼트 수)

 

 

'기타' 카테고리의 다른 글

테넌트  (0) 2020.07.23
TCP Status 상태에 대해서  (1) 2020.07.15
TCP 통계수치 변화 (장애 상황)  (0) 2020.07.15
TCP 통계  (0) 2020.07.14
Kerberos Setup (KR)  (0) 2019.08.22
500 Error on Confluence Startup (KR)  (2) 2019.07.29

안녕하세요 쿤드입니다. 🍀

netstat --statistics 명령부터 시작해보겠습니다. (nstat 명령이 훨씬 간결하긴하지만..)

처음에는 각각의 인자들이 무엇을 의미하는지 확인하려고 했으나
이 페이지를 작성하다보니 하나씩 찾다보니 의미만 아는것은 별 필요가 없는것 같았습니다.

 

장애 당시를 기준으로 확인하는것이 좋을것 같아서 그때 확인한 factor들에 대해서

아래에 따로 정리해두었습니다.

작년에 제가 다니던 회사에서 중간에서 gateway역할을 해주는 application의 오류로 장애가 3시간정도 발생한적이 있었는데

그 당시 tcp 통계 변화를 바탕으로

내부적인 application 장애가 발생해서 외부에서 유입되는 traffic 처리를 못한 경우 어떤 차이가 발생하는지를 확인 해보도록 하겠습니다.

 

아래에 있는 내용들은 netstat으로 확인한 통계 값인데 

무엇을 의미하는건지 모르면 여기에 각각 설명이 잘 나와있습니다.

혹은 Linux Document

 

Ip:
    15829871449 total packets received (InReceives)
    0 forwarded (ForwDatagrams)
    0 incoming packets discarded (InDiscards)
    15829871405 incoming packets delivered (InDelivers)
    14182698760 requests sent out (OutRequests)
    31 outgoing packets dropped
    16 dropped because of missing route (OutNoRoutes)
    143 fragments failed
Icmp:
    12710040 ICMP messages received (InMsgs)
    167 input ICMP message failed. (InErrors)
    ICMP input histogram: 
        destination unreachable: 12263649 (InDestUnreachs)
        timeout in transit: 420248 (InTimeExcds)
        source quenches: 6 (InSrcQuenchs)
        redirects: 92 (InRedirects)
        echo requests: 26045 (InEchos)
    28937 ICMP messages sent
    0 ICMP messages failed
    ICMP output histogram:
        destination unreachable: 2892 (OutDestUnreachs)
        echo replies: 26045 (OutEchoReps)
IcmpMsg:
        InType3: 12263649
        InType4: 6
        InType5: 92
        InType8: 26045
        InType11: 420248
        OutType0: 26045
        OutType3: 2892
Tcp:
    25768376 active connections openings (TcpActiveOpens)
    647707490 passive connection openings (TcpPassiveOpens)   
    4647341 failed connection attempts (AttemptFails)
    31117340 connection resets received (EstabResets)
    3537 connections established (CurrEstab) https://tools.ietf.org/html/rfc793   
    15817063195 segments received (InSegs)
    16491280655 segments send out (OutSegs)
    986318177 segments retransmited (RetransSegs)
    7440 bad segments received. (InErrs)
    91126171 resets sent (OutRsts)
Udp:
    95601 packets received (InDatagrams)
    2569 packets to unknown port received. (NoPorts)
    0 packet receive errors (InErrors)
    111544 packets sent (OutDatagrams)
    0 receive buffer errors (RcvbufErrors)
    0 send buffer errors (SndbufErrors)
UdpLite:
TcpExt:
    42045 SYN cookies sent (SyncookiesSent)
    12143 SYN cookies received (SyncookiesRecv)
    60209039 invalid SYN cookies received (SyncookiesFailed)
    4647134 resets received for embryonic SYN_RECV sockets (EmbryonicRsts)
    3821 packets pruned from receive queue because of socket buffer overrun (PruneCalled)
    63491 ICMP packets dropped because they were out-of-window (OutOfWindowIcmps)
    22286 ICMP packets dropped because socket was locked (LockDroppedIcmps)
    107834482 TCP sockets finished time wait in fast timer (TW)
    46352300 packets rejects in established connections because of timestamp (PAWSEstab)
    607439027 delayed acks sent (DelayedACKs)
    632566 delayed acks further delayed because of locked socket (DelayedACKLocked)
    Quick ack mode was activated 199302465 times (DelayedACKLost)
    208055 SYNs to LISTEN sockets dropped (ListenDrops)
    418093 packets directly queued to recvmsg prequeue. (TCPPrequeued)
    122606 bytes directly in process context from backlog (TCPDirectCopyFromBacklog)
    79146389 bytes directly received in process context from prequeue (TCPDirectCopyFromPrequeue)
    1574327100 packet headers predicted (TCPHPHits)
    402495 packets header predicted and directly queued to user (TCPHPHitsToUser)
    7766206385 acknowledgments not containing data payload received (TCPPureAcks)
    559462251 predicted acknowledgments
    24017 times recovered from packet loss due to fast retransmit
    72915270 times recovered from packet loss by selective acknowledgements
    586 bad SACK blocks received
    Detected reordering 889310 times using FACK
    Detected reordering 465211 times using SACK
    Detected reordering 697 times using reno fast retransmit
    Detected reordering 13789060 times using time stamp
    6344097 congestion windows fully recovered without slow start
    10638781 congestion windows partially recovered using Hoe heuristic
    1716234 congestion windows recovered without slow start by DSACK
    43272810 congestion windows recovered without slow start after partial ack
    TCPLostRetransmit: 1784385
    13185 timeouts after reno fast retransmit
    15322792 timeouts after SACK recovery
    26945066 timeouts in loss state
    104358514 fast retransmits
    30761536 forward retransmits
    72817949 retransmits in slow start
    189678472 other TCP timeouts
    TCPLossProbes: 324536377
    TCPLossProbeRecovery: 76481412
    12218 classic Reno fast retransmits failed
    27270545 SACK retransmits failed
    200116946 DSACKs sent for old packets (TCPDSACKOldSent)
    3581427 DSACKs sent for out of order packets 
    188637563 DSACKs received
    1897085 DSACKs for out of order packets received
    17269734 connections reset due to unexpected data (TCPAbortOnData)
    994645 connections reset due to early user close (TCPAbortOnClose)
    71206457 connections aborted due to timeout (TCPAbortOnTimeout)
    20 times unable to send RST due to no memory
    TCPSACKDiscard: 2614 (Number of SACK blocks are invalid)
    TCPDSACKIgnoredOld: 457719 (Number of DSACK block is invalid, undo_marker not set)
    TCPDSACKIgnoredNoUndo: 94644730 (Number of DSACK block is invalid, undo_marker set)
    TCPSpuriousRTOs: 3443956 (Number of The spurious retransmission timeout detected by the `F-RTO`_ algorithm)
    * skb: The linux networking stack stores data in sk_buff struct
    TCPSackShifted: 17209501 (Number of skb is shifted)
    TCPSackMerged: 57304616 (Number of skb is merged)
    TCPSackShiftFallback: 234570612 (Number of TCP stack doesn't merge it for some reasons.)
    TCPBacklogDrop: 43
    IPReversePathFilter: 3
    TCPReqQFullDoCookies: 42045
    TCPRetransFail: 271
    TCPRcvCoalesce: 606120335
    * OFO: Out Of Order
    TCPOFOQueue: 154893248 (Number of packets queued in OFO queue)
    TCPOFOMerge: 3581444 (Number of packets in OFO that were merged with other packets)
    TCPChallengeACK: 2105995
    TCPSYNChallenge: 64987
    TCPFastOpenCookieReqd: 3824
    TCPSpuriousRtxHostQueues: 332
    TCPAutoCorking: 19132
    TCPWantZeroWindowAdv: 6989
    TCPSynRetrans: 106752693 (Number of SYN and SYN/ACK retransmits to break down retransmissions into SYN,
                                                  fast-retransmits, timeout retransmits, etc.  참고링크)

    TCPOrigDataSent: 11168295644 (Number of outgoing packets with original data, 참고링크)
    TCPHystartTrainDetect: 97852 (Number of  the ACK train length threshold is detected)
    * CWND: Congestion Window
    TCPHystartTrainCwnd: 2647949 (The sum of CWND detected by ACK train length)
    TCPHystartDelayDetect: 21988563 (Number of the packet delay threshold is detected)
    TCPHystartDelayCwnd: 781061970 (The sum of CWND detected by packet delay)
    TCPACKSkippedSynRecv: 1717067 (If the ACk sending frequency is higher than tcp_invalid_ratelimit allows, then +1)
    * PAWS: Protect Against Wrapped Sequence numbers
    TCPACKSkippedPAWS: 1738488
    TCPACKSkippedSeq: 38312
    TCPACKSkippedFinWait2: 2294
    TCPACKSkippedTimeWait: 230801
    TCPACKSkippedChallenge: 8756
IpExt:
    InNoRoutes: 41
    InOctets: 8387403650946
    OutOctets: 12141527324794
    InNoECTPkts: 14298811581
    InECT1Pkts: 279253858
    InECT0Pkts: 271928848
    InCEPkts: 981945413

 

 

그런데 그 설명을 번역만 하는것으로는 도무지 뜬구름 잡는 얘기 같아서 하나도 이해가 가지 않습니다.

일단은 이 수치가 무엇을 의미하는지 먼저 알아보고

이 중에서 필요한것만 따로 모아서 다시 보아야 겠습니다.

 

TCP 통계는 TCP state diagram과 같이 봅니다.

 

TCP 통계를 카테고리화해서 묶어서 보면 한눈에 들어와서 tcp 통계 항목들이 좀 보입니다.
https://perthcharles.github.io/2015/11/10/wiki-netstat-proc/

그마나 찾긴했으나 제가 사용하는 OS와 다른지 통계 factor에 차이가 있습니다.

적당히 느낌만 가지고 넘어갑니다.

category Involve Counters
Realtime RtoAlgorithm、RtoMin、RtoMax、MaxConn
Connection ActiveOpens、PassiveOpens、AttemptFails、CurrEstab、EstabResets
Packet InSegs、OutSegs、RetransSegs、InErrs、OutRsts、InCsumErrors、EmbryonicRsts
syncookies SyncookiesSent、SyncookiesRecv、SyncookiesFailed
TIME_WAIT recycle TW、TWRecycled、TWKilled、TCPTimeWaitOverflow
RTO frequency TCPTimeouts、TCPSpuriousRTOs、TCPLossProbes、TCPLossProbeRecovery、
TCPRenoRecoveryFail、TCPSackRecoveryFail、
TCPRenoFailures、TCPSackFailures、
TCPLossFailures
Retrans Quantity TCPFastRetrans、TCPForwardRetrans、
TCPSlowStartRetrans、TCPLostRetransmit、
TCPRetransFail
FastOpen TCPFastOpenActive、TCPFastOpenPassive、
TCPFastOpenPassiveFail、TCPFastOpenListenOverflow、
TCPFastOpenCookieReqd
MD5 TCPMD5NotFound、TCPMD5Unexpected
DelayedACK DelayedACKs、DelayedACKLocked、DelayedACKLost、
TCPSchedulerFailed
DSACK TCPDSACKOldSent、TCPDSACKOfoSent、
TCPDSACKRecv、TCPDSACKOfoRecv、
TCPDSACKIgnoredOld、TCPDSACKIgnoredNoUndo
Reorder TCPFACKReorder、TCPSACKReorder、
TCPRenoReorder、TCPTSReorder
Recovery TCPRenoRecovery、TCPSackRecovery、
TCPRenoRecoveryFail、TCPSackRecoveryFail
Abort TCPAbortOnData、TCPAbortOnClose、
TCPAbortOnMemory、TCPAbortOnTimeout、
TCPAbortOnLingerTCPAbortFailed

 

 

 

'기타' 카테고리의 다른 글

TCP Status 상태에 대해서  (1) 2020.07.15
TCP 통계수치 변화 (장애 상황)  (0) 2020.07.15
TCP 통계  (0) 2020.07.14
Kerberos Setup (KR)  (0) 2019.08.22
500 Error on Confluence Startup (KR)  (2) 2019.07.29
squid proxy  (0) 2018.12.19

감사(audit)에서 access control을 하는데 

centos 각 서버의 계정에 대해서 이를 관리하는것이 너무 불편한다.

Kerberos를 도입한다.

도입했던 이력을 아래에 정리한다.

 

목차

  • kerberos server
  • kerberos client
  • macos

Kerberos Server

Install

1. 작업 환경

$ cat /etc/system-release
Amazon Linux release 2 (Karoo)

2. 설치한 패키지 목록

  • krb5 관련
  • ntp
$ sudo yum list installed | grep krb
krb5-devel.x86_64                     1.15.1-19.amzn2.0.3            @amzn2-core
krb5-libs.x86_64                      1.15.1-19.amzn2.0.3            @amzn2-core
krb5-server.x86_64                    1.15.1-19.amzn2.0.3            @amzn2-core
krb5-workstation.x86_64               1.15.1-19.amzn2.0.3            @amzn2-core
pam_krb5.x86_64                       2.4.8-6.amzn2.0.2              @amzn2-core

$ sudo yum list installed | grep ntp
fontpackages-filesystem.noarch        1.44-8.amzn2                   @amzn2-core

참고링크

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/managing_smart_cards/installing-kerberos

https://gist.github.com/ashrithr/4767927948eca70845db

 

설정

1. EC2 인스턴스 2대 생성

- master, slave로 HA 구성했다.

 

2. DNS 설정

Route 53에 2개의 도메인을 추가했다. (abcdef.com은 실제 도메인이름으로 바꿔야함

- kdc.abcdef.com

- kdc2.abcdef.com

 

 

설정파일

 

1. /etc/krb5.conf 설정

- realm에 세팅할 도메인은 '대문자'로 해야한다.

$ cat /etc/krb5.conf
# Configuration snippets may be placed in this directory as well
includedir /etc/krb5.conf.d/

[logging]
 kdc = FILE:/var/log/kerberos/krb5kdc.log
 admin_server = FILE:/var/log/kerberos/kadmin.log
 default = FILE:/var/log/kerberos/krb5lib.log

[libdefaults]
 default_realm = ABCDEF.COM
 dns_lookup_realm = false
 dns_lookup_kdc = false
 rdns = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true

[realms]
 ABCDEF.COM = {
  kdc = kdc.abcdef.com:88
  kdc = kdc2.abcdef.com:88
  admin_server = kdc.abcdef.com:749
  default_tkt_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 aes256-cts-hmac-sha384-192 aes128-cts-hmac-sha256-128 des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac des-cbc-crc des-cbc-md5 des-cbc-md4
  default_tgs_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 aes256-cts-hmac-sha384-192 aes128-cts-hmac-sha256-128 des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac des-cbc-crc des-cbc-md5 des-cbc-md4
  permitted_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 aes256-cts-hmac-sha384-192 aes128-cts-hmac-sha256-128 des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac des-cbc-crc des-cbc-md5 des-cbc-md4
 }

[domain_realm]
# .example.com = EXAMPLE.COM
# example.com = EXAMPLE.COM   

 

 

2. /var/kerberos/krb5kdc/kdc.conf 설정

[kdcdefaults]
 kdc_ports = 88
 kdc_tcp_ports = 88

[realms]
 ABCDEF.COM = {
  kadmind_port = 749
  max_life = 9h 0m 0s
  max_renewable_life = 7d 0h 0m 0s
  master_key_type = des3-hmac-sha1
  supported_enctypes = aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal des3-cbc-sha1:normal arcfour-hmac-md5:normal
  database_name = /var/kerberos/krb5kdc/principal
  admin_keytab = /var/kerberos/krb5kdc/kadm5.keytab
  acl_file = /var/kerberos/krb5kdc/kadm5.acl
  dict_file = /var/kerberos/krb5kdc/kadm5.dict
  key_stash_file = /var/kerberos/krb5kdc/.k5.ABCDEF.COM
 }

 

 

3. /var/kerberos/krb5kdc/kadm5.acl 설정

*/admin@ABCDEF.COM  *

 

나머지 세팅

 

1. KDC database 생성

kdb5_util create -r ABCDEF.COM -s

 

 

2. KDC admin 생성

# kadmin.local
kadmin.local:  addprinc account/admin@ABCDEF.COM
     
NOTICE: no policy specified for "admin/admin@ABCDEF.COM";
assigning "default".

Enter password for principal admin/admin@ATHENA.MIT.EDU:  (Enter a password.)
Re-enter password for principal admin/admin@ATHENA.MIT.EDU: (Type it again.)

Principal "admin/admin@ABCDEF.COM" created.
 
kadmin.local:

 

 

3. KDC database 백업 (링크에 복구 방법도 있음)

#!/bin/bash

/usr/sbin/kdb5_util dump /var/kerberos/slave_datatrans


/usr/sbin/kprop -f /var/kerberos/slave_datatrans mgmt-krb-kdc02.abcdef.com > /dev/null
  • 참고로 전달할 도메인 정보는 /etc/hosts에 있다.
% cat /etc/hosts

... 
10.100.125.156     mgmt-krb-kdc02.abcdef.com mgmt-krb-kdc02

 

4. 데몬 설정

systemctl start krb5kdc.service
systemctl start kadmin.service
systemctl enable krb5kdc.service
systemctl enable kadmin.service

 

Kerberos Client

Install

yum --disablerepo=*  --enablerepo=base,update install -y dmidecode krb5-libs

설정

참고로 ec2 1대에 nginx를 두고 스크립트를 불러다가 client로 동작할 서버에 세팅을 한다. 
대략 이런 명령을 이용함
curl -s krb5-client.abcdef.com/seeds/krb-svr-config | /bin/bash

위의 ec2에 flask로 간단하게 구현한 api 서버를 두고 잡다한(계정 추가, 변경, 삭제, ...) 처리를한다.

파일설정

1. /etc/hosts 설정 

  • 필요에 따라서 설정한다.

2. /etc/ssh/sshd_config 설정

  • 필요에 따라서 설정한다.

3. ntp update 수행

ntpdate -u pool.ntp.org

4. kadmin에서 신규 서버 principal 등록, keytab 생성

# addpric
/usr/bin/kadmin -p account/admin -w RkaWkrdldi -q "addprinc -randkey host/dev1-api-all.abcdef.com"

# ktadd
/usr/bin/kadmin -p account/admin -w RkaWkrdldi -q ktadd -k "/home/ec2-user/seeds/keytabs/dev1-api-all.abcdef.com host/dev1-api-all.abcdef.com"

# chmod
chmod og+r /home/ec2-user/seeds/keytabs/dev1-api-all.abcdef.com

5. kdc hosts 파일에 등록

cat /home/ec2-user/seeds/hosts

10.100.56.52      dev1-api-lucky21.abcdef.com       dev1-api-lucky201              
10.100.56.51      dev1-api-lucky11.abcdef.com       dev1-api-lucky101              
10.100.56.50      dev1-api-lucky01.abcdef.com       dev1-api-lucky001              
10.100.56.21      dev1-api-point11.abcdef.com     dev1-api-point101                
10.100.56.22      dev1-api-point12.abcdef.com     dev1-api-point12                 
10.100.56.20      dev1-api-point01.abcdef.com     dev1-api-point001                
10.100.56.23      dev1-api-point21.abcdef.com     dev1-api-point201                
10.100.56.24      dev1-api-point22.abcdef.com     dev1-api-point22                 
10.100.0.162      dev1-proxy-out21.abcdef.com        dev1-proxy-out201             
10.100.0.161      dev1-proxy-out11.abcdef.com        dev1-proxy-out101    

6. 이번엔 4단계에서 생성했던 keytab 파일을 실제 kerberos client에 복사해둔다.

/etc/krb5.keytab

 

addprinc, ktadd 이렇게하고 생성한 keytab 파일을 kerberos client에 옮겨두어야 한다. 

그리고 그와 관련해서 hosts 파일도 갱신해야한다.

이를 좀 편리하게 하기 위해서 ec2에 nginx + gunicorn + flask로 구성한 api 서버를 두고 처리하고 있다.

 

MacOS 사용자 설정

내 pc에서 ssh로 접근할 때 사용할거라서 내거에도 설정해야한다.

 

1. /etc/krb5.conf 설정

[libdefaults]
default_realm = ABCDEF.COM
allow_weak_crypto = false
rdns = false

[realms]
ABCDEF.COM = {
kdc = kdc.abcdef.com
kdc = kdc2.abcdef.com
admin_server = kdc.abcdef.com
kpasswd_server = kdc.abcdef.com
}

 

2.  /etc/ssh/ssh_config 설정

  • 참고로 MacOS update 하고나면 이 설정이 원복 되기도 하므로 update 이후엔 확인 해보아야 한다.
GSSAPIAuthentication yes    => Allow authentication protocol for ssh kerberos support
StrictHostKeyChecking no     

3. MacOS의 터미널에 접속해서 kinit을 한다.

kinit --kdc-hostname=kdc.abcdef.com,kdc2.abcdef.com sfixer@ABCDEF.COM

그리고 나서 제대로 되는지 확인한다.

% ssh sfixer@10.100.125.143
% ssh sfixer@dev1-api-all
...

'기타' 카테고리의 다른 글

TCP 통계수치 변화 (장애 상황)  (0) 2020.07.15
TCP 통계  (0) 2020.07.14
Kerberos Setup (KR)  (0) 2019.08.22
500 Error on Confluence Startup (KR)  (2) 2019.07.29
squid proxy  (0) 2018.12.19
reverse proxy 개념  (0) 2018.12.19

기존에 AWS EC2의 m3.large에 jira, confluence를 설치형으로 운영하고 있었다.

(nginx, mysql도 같은 인스턴스에 설치하여 운용)

 

최근들어서 메모리 부족 이슈가 자꾸 발생한다.

  •  java.lang.OutOfMemoryError: Java heap space

일단은 스케줄 작업 시간을 분산해보았다.

confluence schedule job

 

몇일 괜찮더니 여전히 또 메모리 부족으로 confluence 접근이 안된다.

EC2 사양을 높이고 m3.large -> m3.xlarge로 (7.5G -> 15G) 메모리를 높였다.

 

메모리 사용하는 프로세스

  • java/confluence
  • java/jira
  • nginx
  • mysql

 

startup.sh 명령을 실행해서 띄웠다.

 

안되고 500 ERROR가 난다.

29-Jul-2019 01:51:06.145 SEVERE [http-nio-8090-exec-2] org.apache.catalina.core.StandardHostValve.custom Exception Processing ErrorPage[errorCode=500, location=/500page.jsp]

 com.atlassian.util.concurrent.LazyReference$InitializationException: java.lang.NullPointerException

        at com.atlassian.util.concurrent.LazyReference.getInterruptibly(LazyReference.java:149)

        at com.atlassian.util.concurrent.LazyReference.get(LazyReference.java:112)

        at com.atlassian.confluence.plugin.servlet.filter.ServletFilterModuleContainerFilter.getServletModuleManager(ServletFilterModuleContainerFilter.java:23)

        at com.atlassian.plugin.servlet.filter.ServletFilterModuleContainerFilter.doFilter(ServletFilterModuleContainerFilter.java:68)

        at com.atlassian.plugin.servlet.filter.ServletFilterModuleContainerFilter.doFilter(ServletFilterModuleContainerFilter.java:63)

        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)

        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

        at com.atlassian.confluence.web.filter.DebugFilter.doFilter(DebugFilter.java:50)

        at com.atlassian.core.filters.AbstractHttpFilter.doFilter(AbstractHttpFilter.java:31)

        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)

        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

        at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:721)

        at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:468)

        at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:391)

        at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:318)

        at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:439)

        at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:305)

        at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:399)

        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180)

        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)

        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)

        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)

        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)

        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668)

        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1521)

        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1478)

        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

        at java.lang.Thread.run(Thread.java:745)

Caused by: java.lang.NullPointerException

        at com.atlassian.spring.container.ContainerManager.getComponent(ContainerManager.java:33)

        at com.atlassian.confluence.util.LazyComponentReference$Accessor.get(LazyComponentReference.java:46)

        at com.atlassian.util.concurrent.Lazy$Strong.create(Lazy.java:85)

        at com.atlassian.util.concurrent.LazyReference$Sync.run(LazyReference.java:321)

        at com.atlassian.util.concurrent.LazyReference.getInterruptibly(LazyReference.java:143)

        ... 29 more

 

아...... 일단 구글링

https://www.google.com/search?newwindow=1&ei=pFg-XcOuMpXMvwTrhKbABA&q=org.apache.catalina.core.StandardHostValve.custom+Exception+Processing+ErrorPage%5BerrorCode%3D500%2C+location%3D%2F500page.jsp%5D&oq=org.apache.catalina.core.StandardHostValve.custom+Exception+Processing+ErrorPage%5BerrorCode%3D500%2C+location%3D%2F500page.jsp%5D&gs_l=psy-ab.3...12614.12614..12886...0.0..0.0.0.......0....2j1..gws-wiz.Xc4qbAH0AaA&ved=0ahUKEwjDkOSgidnjAhUV5o8KHWuCCUgQ4dUDCAo&uact=5

 

org.apache.catalina.core.StandardHostValve.custom Exception Processing ErrorPage[errorCode=500, location=/500page.jsp] - Google

2013. 5. 24. · Well, we get a 500 error on the home page after starting up at least. The error we see in the ... StandardHostValve custom SEVERE: Exception Processing ErrorPage[errorCode=500, location=/500page.jsp] java.lang. NullPointerException at ... do

www.google.com

 

다행히 1번째 결과가 나의 상황과 유사하다.

링크를 열어보니 희망이 생긴다.

https://community.atlassian.com/t5/Confluence-questions/500-Error-on-Confluence-Startup/qaq-p/393445

 

500 Error on Confluence Startup

I am unable to start up our Confluence instance. Well, we get a 500 error on the home page after starting up at least. The error we see in the web page is: exception com.atlassian.util.concurrent.LazyReference$InitializationException: java.lang.NullPointer

community.atlassian.com

 

링크의 댓글을 따라가본다. (That did it for me, thanks! 라고 한다. 이거 왠지 될거 같다.)

 

How to clear Confluence plugins cache - Atlassian Documentation

How to clear Confluence plugins cache

confluence.atlassian.com

왠지 느낌이 이거같다. 플러그인 캐쉬 문제

 

solution for this error

다 풀릴것 같은 문제가 <confluence-home>을 못찾고 또 지연된다.

결국 find로 뒤져보니 저 디렉토리가 똑같이 존재한다.

 

언급된 디렉토리를 삭제하진 않고 일단 mv 명령어로 다른 path로 옮기고

confluence를 재시작하였다.

 

시작하면서 저 디렉토리들을 새로 만든다.

그러다보니 기동하는데 오래걸린다.  (참고로 default 8090 port로 띄움)

 

띄우고나서 확인, 아까는 500 ERROR였는데 200 OK 뜬다. 

$ wget http://localhost:8090
--2019-07-29 04:19:04--  http://localhost:8090/
Resolving localhost (localhost)... 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:8090... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://localhost:8090/login.action?os_destination=%2Findex.action&permissionViolation=true [following]
--2019-07-29 04:19:04--  http://localhost:8090/login.action?os_destination=%2Findex.action&permissionViolation=true
Reusing existing connection to localhost:8090.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: ‘index.html

index.html                                     [ <=>                                                                                    ]  19.64K  --.-KB/s   in 0.002s 

2019-07-29 04:19:04 (11.1 MB/s) - ‘index.html’ saved [20107]

 

잘된다.

'기타' 카테고리의 다른 글

TCP 통계  (0) 2020.07.14
Kerberos Setup (KR)  (0) 2019.08.22
500 Error on Confluence Startup (KR)  (2) 2019.07.29
squid proxy  (0) 2018.12.19
reverse proxy 개념  (0) 2018.12.19
Subnet mask 개념  (0) 2018.11.14
  1. nblack00 2019.08.07 18:05 신고

    라즈베리파이에서 오는 좌표값을 데이터베이스로 전송해서 테이블을 짜야하는데 도저히 감이 잡히지 않아서요 ㅠㅠ 혹시 괜찮으시다면 저좀 도와주실수 있으세요 ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠ?

    • Nj 2019.08.16 13:57 신고

      제가 했던 방식은 테이블을 사용하지 않았어요. redis를 사용해서 key/value 방식으로만 했었습니다.

      이것을 사용해서 redis에 값을 넣었습니다.
      - library: from redis_collections import List
      - key: rp3:시리얼번호:20190816
      - vlaue: 조도센서의 측정값

+ Recent posts