얼마전 호스팅한 서버에서 중국이 해킹해… 초당 2MB 정도로 패킷을 거의 2주간 전송하고 있다고 해서 netstat을 정말 열심히 사용해 어떤 프로세스가 그러한 요청을 보내는지 알아보려고 하다가 netstat을 좀 써보게 되었는데 그 내용을 포스팅한다.

환경

  • Ubuntu 16.04


netstat이란?

  • netstat : network statistics의 줄임말로 네트워크 인터페이스나 프로토콜 상에서의 통계를 보여주는 소프트웨어 혹은 도구입니다. 대체로 네트워크의 성능을 측정하고 네트워크 상의 문제점을 파악할 때 많이 쓰입니다.


기본적인 netstat의 명령어를 사용하시면

  • 외부와 통신하는 상태를 알려주는 Active Internet connections

  • 내부에서 프로세스들끼리 소통하는 상태들을 알려주는 Active UNIX domain sockets에 대한 내용을 확인 할 수 있습니다.


netstat 사용법 및 간단한 옵션

netstat의 예시

기본적인 명령어는 아래와 같으며 명령어를 실행하면 다음과 같은 결과가 나옵니다.(Active Connections의 경우)

$ netstat

Netstat First

  • Proto : 해당 통신이 사용하는 프로토콜을 나타냅니다.
  • Recv-Q and Send-Q : 해당 통신이 사용할 때 소켓 사이즈 버퍼를 의미하며 Recv-Q의 경우 recv()를 통해 처리 받지 못한 데이터를 의미하며 Send-Q의 경우 send()를 통해 보냈지만 아직 완전하게 외부로 보내지지 않은 데이터의 크기를 의미합니다.
  • Local Address and Foreign Address : 말 그대로 해당 통신에서 나가는 내 주소와 목적지에 해당하는 주소를 의미합니다.
  • State : ESTABLISHED, LISTEN과 같은 상태를 나타냅니다. 상세한 부분은 TCP/IP 통신을 따로 보시면 되고 나중에 시간되면 이 부분도 포스팅하겠습니다.


netstat에 옵션을 주기

이제 netstat 명령어에 옵션을 주어 더 상세한 정보를 보도록 하겠습니다. 모든 옵션들을 보여주기에는 힘드니 제가 특정 프로세스를 확인 할 때 사용하였던 옵션들을 나열하겠습니다.

  • “-a” : ESTABLISHED 뿐만 아닌 모든 State에 대한 소켓들의 정보를 보여줍니다.
  • “-n” : 도메인 명이 아닌 숫자 ip주소를 표시해줍니다.
  • “-p” : 어떤 프로세스에서 해당 통신을 사용하고 있는 지를 보여줍니다.
$ netstat -anp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:[port]           0.0.0.0:*               LISTEN      2007/beam
tcp        0      0 0.0.0.0:[port]           0.0.0.0:*               LISTEN      1498/redis-server 0
tcp        0      0 0.0.0.0:[port]           0.0.0.0:*               LISTEN      1816/epmd
tcp        0      0 0.0.0.0:[port]           0.0.0.0:*               LISTEN      1538/sshd

Netstat with options


다음에는 더 공부해서 네트워크와 Linux에서 환경설정을 어떻게 하면 더 튼튼한지 이런부분에 대해서 더 포스팅해보겠습니다.

서버를 호스팅 받았을 때 Ubuntu 14.04 LTS x64 기준으로 어떻게 유저를 추가하는지에 대해서 포스팅한다. 5분 컷!


맥에서 ssh로 서버에 접속하기

맥의 터미널에서는 바로 ssh에 접속이 가능하다.

22번 포트가 아닌 다른 포트를 사용하고 싶다면 -p를 통해서 포트번호를 입력 받을 수 있다.

$ ssh [원격지서버 User ID]@[Host]
...
$ ssh [원격지서버 User ID]@[Host] -p [포트번호]

예시

$ ssh root@123.456.789.123 -p 22


root계정의 비밀번호 변경하기

임대받은 서버의 경우에는 비밀번호를 임시로 제공해주는데 이를 변경하고 싶다면 다음과 같다. 아주 간단하게 다음 명령어만으로 가능하다. (여기까지는 금방금방!)

$ sudo passwd root

이렇게 명령어를 실행해주면 다음 아래와 같이 실행이 된다. 리눅스에서는 비밀번호를 터미널 창에 표시해주지 않는다.

$ sudo passwd root
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully


현재 시스템에 유저를 추가하기

root 계정에 있을때 사용자 유저를 추가하려면 아래 명령어를 치면 간단하게 추가가 가능하다.

$ adduser [추가하는 사용자 이름]

진행하면 아래와 같이 커맨드 창에 나오면 필요한 정보들은 입력해주시면 됩니다.

$ adduser nelp
Adding user `nelp' ...
Adding new group `nelp' (1002) ...
Adding new user `nelp' (1002) with group `nelp' ...
Creating home directory `/home/nelp' ...
Copying files from `/etc/skel' ...
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for nelp
Enter the new value, or press ENTER for the default
	Full Name []:
	Room Number []:
	Work Phone []:
	Home Phone []:
	Other []:
Is the information correct? [Y/n] y

P.S. 유저를 위의 방식으로만 추가하면 sudo 명령어를 사용할 때 sudoers가 아니어서 sudo 명령어를 사용 할 수 없다고 나오는데 그럴 때는 처음부터 아래처럼 유저를 추가하시거나 위에처럼 추가하시고 아래 명령어를 실행하셔도 됩니다.

adduser [추가하는 사용자 이름] sudo

혹은

usermod -aG sudo [추가하는 사용자 이름]


현재 시스템에 유저를 삭제하기

간단하다. 다음 아래와 같은 명령어를 사용하면 됩니다.

$ deluser [User Name]

이렇게 하면 계정만 삭제된다고 하며 모든 정보들을 함께 삭제하려면 다음과 같이 -remove-all-files를 붙여줘야 합니다.

$ deluser -remove-all-files [User Name]


현재 시스템의 유저 정보를 보기

유저 정보 확인

유저 정보를 볼 수 있는 방법은 /etc/passwdcat 명령어를 통해서 출력하면 됩니다.

$ cat /etc/passwd

그러면 다음과 같이 :으로 구분된 정보들이 출력됩니다.

$ cat /etc/passwd
...
twpower:x:1000:1000:,,,:/home/twpower:/bin/bash
...

:을 통해서 구분된 모습이 보이며 각 위치마다 나타내는 정보는 다음과 같습니다.

[사용자계정]:[x(비밀번호)]:[사용자 ID]:[Group ID]:[,로 구분된 계정 정보]:[홈 디렉토리]:[로그인 쉘]


유저 암호 정보 확인

유저 암호정보를 볼 수 있는 방법은 /etc/shadowcat 명령어를 통해서 출력하면 됩니다.

$ cat /etc/shadow

그러면 다음과 같이 :으로 구분된 정보들이 출력됩니다.

$ cat /etc/shadow
...
twpower:$6$qujW8gO(생략)hpT3z.:17242:0:99999:7:::
...


참고자료

다음 아래 홈페이지에서 많은 내용을 참고하여 토대로 작성하였습니다.

http://mirwebma.tistory.com/112

앞에서 UTC, Timezone, ISO 8601 그리고 python에서 그러한 형태에 따라서 어떻게 자료를 가공해야하는지에 대해서 다루었다면 javascript json으로 date관련 문자열을 넘겨 받았을 때 Date객체로 어떻게 변환하는지에 대해서 알아본다.


이전 포스트

UTC, Timezone, ISO 8601의 개념이랑 python에서 간단한 예제를 미리 보고 싶으신 분은 ISO 8601과 UTC 그리고 python 예제를 참고하시길 바랍니다!


Javascript 날짜와 시간 관련 class

Javascript에서는 Date라는 class를 사용해서 날짜 관련 처리를 해주는데 기본적으로 아래와 같은 기능들을 모두 지원해준다.(편하다)

  • 현재 컴퓨터에서 설정된 시간과 날짜를 참고해 Date관련 클래스를 생성해주고 년/월/일T시:분:초.밀리초의 정보를 다 get 및 set이 가능하다.
  • 현재 컴퓨터에서 설정된 시간 기준으로 UTC 표준시에 관한 부분들도 다 get과 set을 지원해준다.
  • ISO 8601 형식 및 JSON(UTC 기준시로 나타내줍니다. - 즉 Timezone이 적용된 ISO 8601형태로 뽑아줍니다.)

자세한 설명은 코드를 직접 작성하기보다 w3shcools에 너무 잘 나와있어서 링크를 첨부하겠습니다.


JSON(in ISO 8601 format) => Date객체

그러먼 JSON으로 온 date관련 문자열을 어떻게 Date클래스로 만들 수 있는지 보도록 하겠습니다.

기본적으로 Date class에 있는 contructor에서 자동으로 파싱을 해서 생성합니다.

var date = new Date("2017-03-17T09:38:51.249Z")

/*
다음 아래들도 다 같은 표현입니다.
*/

date = new Date("2017-03-17T09:38:51.249Z")

// KST(UTC로 부터 9시간이 더해진 한국 표준시)를 나타내는 표현식으로도 가능합니다.
date = new Date("2017-03-17T09:38:51.249+09:00")

P.S. 기본적으로 Timezone에 대한 정보 없이 milliseconds나 날짜로만 입력하면 자동으로 Local Timezone으로 입력이 됩니다.

python에서 datetime class를 이용할 때, javascript에서 Date class를 이용할 때 그리고 java에서 Date class를 이용할 때 종종 보았던 날짜 표시 형식과 그 의미에 관해서 간략하게 알아본다.


UTC와 GMT

UTC

UTC는 Coordinated Universal Time의 줄임말로 1927년 1월 1일부터 시행된 국제 표준시입니다. 이 UTC는 국제 원자시와 윤초 보정을 기반으로 표준화 되어있습니다. 즉, 세계에서 시간을 표현하는 표준시라고 보면됩니다.

GMT

GMT는 Greenwich Mean Time의 줄임말로 그리니치 평균시라고 불리며 런던을 기점으로 하고 웰링턴에서 종점으로 설정 되는 협정 세계시입니다.

UTC vs GMT?

결론부터 말하면 UTC와 GMT는 일상에서는 공통으로 같은 시간을 나타냅니다.(정확하게 들어가면 UTC가 더 정확한 시간을 표현합니다.) 1972년 1월 1일부터 UTC라는 세계 협정시가 사용되었으며 이는 먼저 사용되던 GMT와 기준시가 같기에 요즘날에 혼용해서 사용하게 되었습니다.


UTC를 기준으로 한 시간의 표현과 Timezone

Timezone

이제 위에서 UTC라는 국제표준시로 시간을 정한다는 부분을 설명드렸습니다. 그런데 국가마다 사용하는 시간이 다르기 때문에 공통된 시간대로 묶은 특정 지역을 Timezone이라고 합니다.

우리나라의 경우에는 ISO 8601에 따르면 2017-03-16T17:40:00+09:00와 같은 형식으로 표시된다고 합니다.

아래서 설명을 하겠지만 뒤에 +09:00부분을 통해서 UTC기준시로 9시간이 추가된 시간대라는 것을 표현합니다.

Timezone에 관련된 링크는 다음과 같습니다. Wikipedia - Timezone


ISO 8601

정의

UTC 그리고 Timezone과 함께 문자열의 형태로 시간을 표현하는 방법을 기술해놓은 표준입니다.

몇가지 원칙

  • 년/월/일T시:분:초 처럼 왼쪽에서 오른쪽으로 갈수록 작은 단위어야 합니다.
  • 날짜와 시간은 포맷을 맞추기 위해 0을 붙입니다. EX) 4월 -> 04월
  • 위의 2가지가 중요하다고 생각하며 나머지 3가지는 링크를 참고하시길 바랍니다.Wiki

형태

가장 기본적인 형식(날짜와 시간)은 아래와 같습니다.

2017-03-16T17:40:00+09:00
  • 날짜 : 년-월-일의 형태로 나와있습니다.
  • T : 날짜 뒤에 시간이 오는것을 표시해주는 문자입니다.
  • 시간 : 시:분:초의 형태로 나와있으며 프로그래밍 언어에 따라서 초 뒤에 소수점 형태로 milliseconds가 표시되기도 합니다.
  • Timezone Offset : 시간 뒤에 ±시간:분의 형태로 나와있으며 UTC기준시로부터 얼마만큼 차이가 있는지를 나타냅니다. 현재 위의 예시는 한국시간을 나타내며 UTC기준시로부터 9시간 +된 시간임을 나타냅니다
  • Z or +00:00 : UTC기준시를 나타내는 표시이며 “+00:00”으로 나타내기도 합니다.


Python에서 datetime과 timezone표시

파이썬에서 간단하게 ISO 8601에 따라서 시간을 표시해보는 간단한 코드를 보겠습니다. datetime class를 이용합니다.

특별한 명시 혹은 timezone을 설정해주지 않으면 System의 시간과 timezone에 따라서 시간을 나타내게 됩니다.

test.py

import datetime

#.now() -> 현재 local time
print(str(datetime.datetime.now()))
#.utcnow() -> utc 기준시
print(str(datetime.datetime.utcnow()))
Taewooui-MacBook-Pro:Documents taewoo$ python test.py
2017-03-16 19:55:28.084217
2017-03-16 10:55:28.084274

위와 같이 현재 시간과 UTC 시간이 나오지만 UTC에 대한 정보가 생략되어있습니다. 즉, +00:00과 같은 포맷이 없는데다가 T가 없고 띄어쓰기가 있는걸로 보아 완전한 ISO 8601의 형태가 아닙니다.


test_datetime_in_iso_format.py

import datetime

print(str(datetime.datetime.now().isoformat()))
print(str(datetime.datetime.utcnow().isoformat()))
Taewooui-MacBook-Pro:Documents taewoo$ python test_datetime_in_iso_format.py
2017-03-16T20:02:57.224509
2017-03-16T11:02:57.224592

T도 있고 붙여써서 ISO 8601 형태에 맞지만 아직 timezone의 정보가 들어있지 않습니다.

파이썬 datetime 자체로는 timezone을 지원하지 않습니다. 그래서 pytz와 같은 모듈을 써야합니다.


test_datetime_with_pytz.py

import datetime
import pytz

print(str(datetime.datetime.now(tz=pytz.utc).isoformat()))
Taewooui-MacBook-Pro:Documents taewoo$ python test_datetime_with_pytz.py
2017-03-16T11:08:12.216857+00:00


JSON string date format => Python datetime

JSON은 string의 형태로 datetime의 값이 날아오게 됩니다. 이 때 ISO 8601에 따른 형식일 때 어떻게 python datetime 객체로 바꾸는지에 대한 코드입니다. dateutil.parser를 이용하면 비교적 쉽게 파싱이 가능합니다 :)

import dateutil.parser

print(str(dateutil.parser.parse("2017-03-16T11:08:12.216857+00:00")))
print(str(dateutil.parser.parse("2017-03-16T11:08:12.216857Z")))
2017-03-16 11:08:12.216857+00:00
2017-03-16 11:08:12.216857+00:00

위처럼 UTC 시간으로 나오며 뒤에 타임존 부분도 추가되어있음을 확인 할 수 있습니다. 실제로 테스트 코드도 pytest로 돌려본 결과 같다고 assert를 실행하였을 때 결과가 나왔습니다


하지만 UTC 표준시로 나와있으며 타임존이 표시가 되어있지만 현재 제 지역의 타임존이 추가 되어있지 않습니다ㅠㅠ

이제 현재 컴퓨터에 따른 Timezone을 추가해봅시다.

버전에 따라서 여러 방법이 있지만 pytz를 통해서 2와 3에서 다 사용 할 수 있는 코드는 아래와 같습니다.

test.py

import dateutil.parser
import pytz

# JSON으로 들어온 문자열을 python datetime으로 변환
date=dateutil.parser.parse("2017-03-16T11:08:12.216857+00:00")

# Timezone을 설정
local_timezone = pytz.timezone('Asia/Seoul')

# Timezone에 따라서 새로운 date형식을 변경
local_date = date.replace(tzinfo=pytz.utc).astimezone(local_timezone)

# 출력
print(local_date.isoformat())
Taewooui-MacBook-Pro:Documents taewoo$ python test.py
2017-03-16T20:08:12.216857+09:00


왜 UTC와 ISO 8601을 따라야 할까?

ISO 8601에 따르면 파싱을 할 수 있는 라이브러리가 많으며 전체적으로 호환이 되는 부분이 많습니다. 무엇보다 현재 적용하고 있는 프로젝트와 이전과 비교되면서 느낀거지만 timestamp나 정수형으로 저장이 되어있다면 어디 기준으로 기록된 시간인지에 대한 정보가 없습니다. 이러한 부분에서 보면 불편함이 있더라도 DB에 저장하거나 할 때 각 언어가 지원해주는 날짜 및 시간관련 코드들을 적극 사용하는 부분이 여러 호환에 있어서 이득이라 여겨집니다.

Circle CI에서 빌드를 할 때 터미널에 값을 입력하는 방법을 알아보자


배경

안드로이드로 개발 환경을 만들고 Circle CI에서 빌드를 하는데 [y/n]로 물어보는 부분에서 넘어가지 못하고 있는 상황이 있었는데 구글링을 좀 하고 결과를 찾아서 공유하고자 포스팅을 한다.

방법은 의외로 매우 간단한데… echo 명령어를 써주면 끝난다...

echo 명령어는 echo 다음에 오는 문자열들을 터미널에 출력해주는 역할을 한다.

처음에는 “;y;”와 같이 직접 입력하는 시도를 해봤는데 되지 않았다…


방법

다음 아래처럼 입력하고자 하는 값들 혹은 문자열들을 echo를 통해서 입력하고 |로 다음 명령어를 입력하면 된다.

  • echo y | commands-you-want!

이는 Circle CI뿐만 아니라 다른 CI에서도 적용이 가능하다(쉘 명령어니까!)

circle.yml

general:
  artifacts:
    - /home/ubuntu/Unopen.Lab-Alarm/app/build/outputs/apk/

machine:
  java:
    version: openjdk8

dependencies:
  override:
     - chmod +x gradlew

# 다음 아래처럼 "echo y |" 문만 앞에! 추가하면 됩니다.
test:
  pre:
    - echo y | android update sdk --no-ui --filter build-tools-25.0.2,android-25,extra-android-m2repository