2018년 7월 29일 일요일

spring에서 mariadb로 연동후 웹에서 접근시 jdbc 오류가 발생할때

* 본문은 [코드로 배우는 스프링 웹 프로젝트, 구멍가게 코딩단 지음] 도서를 공부하면서 정리한 글임을 밝힙니다.

2018년 7월 28일 토요일


1. 파티션 분할

Windows가 설치되어 있는 파티션에 함께 설치할 수 없어 리눅스용 파티션 생성

1. 내 컴퓨터 (우클릭) > 관리

2. 저장소 > 디스크 관리 > 파티션 생성할 디스크 선택 > 볼륨 축소 > 크기 지정


2. CentOS 7 ISO 설치

1. CentOS 홈페이지에서 ISO 파일을 다운로드 - https://www.centos.org/download/

(저의 경우에는 DVD ISO 파일을 선택 했습니다)

2. CentOS 설치용 USB 만들기 - http://blog.hangyeong.com/504

★ (주의) 저의 경우에는 YUMI나 기타 다른 Tool로 생성 시, 모두 실패 했습니다.

     문제 해결을 위하여 이곳 저곳 뒤지면서 좋은 글을 발견 했습니다.

     USB 만드는데만 2시간 이상 소비했는데, 위 링크를 참조하여 진행하는게 

     정신 건강에 좋을 것 같습니다.


3. Windows-Linux 멀티부팅 설정 (grub)

★ 해당 과정 진행하지 않으면 Windows 사용 불가합니다.

1. 부팅 시 아래와 같이 메뉴가 출력됨

CentOS Linux 7 (Core), with Linux 3.10.0-229.el7.x86_64

CentOS Linux 7 (Core), with Linux 0-rescue-8a09b1282672463589da9bf081cb9

2. 'c'를 누르면 grub> 이 나오는데 아래 커맨트 입력하여 윈도우 파티션 확인

grub> ls -l

파일 시스템이 NTFS 이고, 파티션이 1024킬로 바이트에서 시작되는 것이라고 함

ex) hd0, msdos1 

3. 리눅스로 부팅 후, 터미널에서 아래와 같이 진행

# cd /boot/grub2

# cp grub.cfg grub.org   // 원본 파일 백업

# vi grub.cfg

vi에서 메뉴 엔트리에 아래 내용 추가

### BEGIN /etc/grub.d/10 linux ###  <- 밑에 아래 내용 추가

menuentry "Windows7 Ulitimate k"{
#insmod NTFS // 윈도우 부팅 시 이 부분에서 오류가 발생하여 삭제함
insmod chain
insmod drivemap
set root=(hd0,msdos1)
chainloader +1
}

저장 후, reboot 하면 윈도우 부트 메뉴가 보일 것 입니다.

만약 보이지 않는다면 윈도우 파티션 정보를 잘못 입력했을 수도 있으므로

파티션 정보를 변경해가면서 확인 하시면 됩니다.


4. 유선 네트워크 설정 

아래 정보는 직접 수행한 것은 아니며, 찾아다니면서 얻은 정보입니다.

네트워크 설정을 추가하여 yum을 사용합시다.

# /etc/rc.d/ini.d/network start

# ifconfig  

# nmcli d 로 네트워크 어댑터가 살아 있는지 확인.

# nmtui  

# vi /etc/sysconfig/network-scripts/ifcfg-enp0s25  

# yum install -y bind-utils <- DNS 

# yum install -y vim <- vi 편집기 업그레이드판

# yum install -y ntsysv <- 서비스관리

# yum install -y system-config-firewall-tui <- 방화벽 관리

# yum install -y system-config-network <- 네트워크 관리

# yum -y install net-tools      <-네트워크 관리툴


무선어댑터 드라이버 설치 (필요 시)

# yum -y install dhcp wireless-tools


출처: http://eeingee.tistory.com/1 [열무아빠의 낙서장]

footer가 화면 하단에 정상적으로 출력되지 않을 경우 해결법


* 본문은 [코드로 배우는 스프링 웹 프로젝트, 구멍가게 코딩단 지음] 도서를 공부하면서 정리한 글임을 밝힙니다.

2013년 10월 3일 목요일

[Libpcap] Libpcap 정리


#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h> // for TCP protocol in transport layer
#include <arpa/inet.h> // include for inet_ntoa()

#include <netinet/in.h> // defined TCP Procotol Type information
                           /* TCP 및 IP Protocol 에 관련된 정보 포함.
                              대표적으로 well-known port number 및 IP 체계 */

#include <pcap.h> // pcap func used errbuf[], errbuf size = 256
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>

#define PCAP_CNT_MAX 1
#define PCAP_SNAPSHOT 1024
#define PCAP_TIMEOUT 100
#define FILTER_RULE "host 192.168.100.100" // Filtering taget IP and Port Number

void packet_view(unsigned char* user, const struct pcap_pkthdr *h, const unsigned char *p);

int main(int argc, char* argv[]) {
char* dev;
char errbuf[PCAP_ERRBUF_SIZE];
bpf_u_int32 net;
bpf_u_int32 mask;                         // struct in_addr은 <netinet/in.h>에 정의.
struct in_addr net_addr, mask_addr;
pcap_t *pd;                                 // struct bpf_program은 <pcap-bpf.h>에 정의.
struct bpf_program fcode;
/* struct bpf_program {
u_int bf_len;
struct bpf_insn *bf_insns;
 } */

/* pcap_lookupdev is find network interface. if finding network interface, it return that found network interface name.
    pcap_lookupdev : fail => return null / success => char* pointer (NIC name) */

if(!(dev = pcap_lookupdev(errbuf))) {
perror(errbuf);
exit(1);
}

if(pcap_lookupnet(dev, &net, &mask, errbuf) < 0) {
perror(errbuf);
exit(1);
}

/* pcap_lookupnet이 반환하는 net, mask 값은 network address, 즉 정수형으로 이루어져있기에 이 값을 숫자 사이에 점을 찍는 IP주소표시법으로 구성된 ASCII 문자열을 가리키는 문자열 포인터를 리턴하는 inet_ntoa()를 이용하여 일반적인 IP주소 형태로 바꾸어 출력함. */

net_addr.s_addr = net;
mask_addr.s_addr = mask;

printf("Device : %s\n", dev);
printf("Net Address : %s\n", inet_ntoa(net_addr)); // 네트워크 주소(정수형) => ASCII (우리가 알고있는 IP주소)
printf("Netmask : %s\n", inet_ntoa(mask_addr));

// pcap_open_live (NIC, capture MAX byte, timeout, errbuf)).
   pcap_open_live is open packet capture interface and that pointer return */

if((pd = pcap_open_live(dev, PCAP_SNAPSHOT, 1, PCAP_TIMEOUT, errbuf)) == NULL) {
perror(errbuf);
exit(1);
}

if(pcap_compile(pd, &fcode, FILTER_RULE, 0, mask) < 0) {
perror(pcap_geterr(pd));
exit(1);
}

if(pcap_setfilter(pd, &fcode) < 0) {
perror(pcap_geterr(pd));
exit(1);
}

// packet read 관련 API에서는 패킷을 읽었을때, Demultiplexing이 되지 않은 완전한 구조의 패킷을 넘겨줌
if(pcap_loop(pd, PCAP_CNT_MAX, packet_view, 0) < 0) {
perror(pcap_geterr(pd));
exit(1);
}
pcap_close(pd);
return 0;

}

void packet_view(unsigned char* user, const struct pcap_pkthdr *h, const unsigned char *p) {
struct ip *iph;
struct tcphdr *tcph;
struct udphdr *udph;
struct ether_header *etherh;
unsigned short e_type;
int cnt;

/* ethernet header와 IP header의 경우 demultiplexing 과정을 거치기 위해 상위 layer의 protocol type을 지정함. ethernet header의 경우 ether_type, IP header는 ip_p가 각 상위 layer의 protocol type을 알려주기 위해 사용됨. 해당 내용은 OSI 7계층의 encapsulation 참조 */

etherh = (struct ether_header *)p;
e_type = ntohs(etherh->ether_type);

printf("-----------------------------------------  \n");
printf("[[ Layer 2 :: Ethernet Header ]]\n");
        // out Ehternet Header information
printf("[ Destination hardware address :: %02x", etherh->ether_dhost[0]);

for(cnt = 1; cnt < ETHER_ADDR_LEN; cnt++)
printf(":%02x", etherh->ether_dhost[cnt]);

printf("]\n[ Source hardware address      :: %02x", etherh->ether_shost[0]);

for(cnt = 1; cnt < ETHER_ADDR_LEN; cnt++)
printf(":%02x", etherh->ether_shost[cnt]);
printf("]\n[ Type :: %x ]\n", etherh->ether_type);

printf("\t-----------------------------------------  \n");
p += sizeof(struct ether_header);

// IP, ARP, RARP Header analyze
if (e_type == ETHERTYPE_IP) {

iph = (struct ip *)p;

printf("\t[IP Packet!]\n");
printf("\t-----------------------------------------  \n");
printf("\t[ IP version                :: %d ]\n", iph->ip_v);
printf("\t[ Header Length             :: %d ]\n", iph->ip_hl);
printf("\t[ Type of Service           :: %d ]\n", iph->ip_tos);
printf("\t[ Total Length              :: %d ]\n", iph->ip_len);
printf("\t[ Identification            :: %d ]\n", iph->ip_id);
printf("\t[ Flags  ================== ::  ]\n");

if ((iph->ip_off) == IP_RF)
printf("\t[      || Reserved flagment :: 0x%x ]\n", IP_RF);
else if((iph->ip_off) == IP_DF)
printf("\t[      || Don't  flagment   :: 0x%x ]\n", IP_DF);

else if((iph->ip_off) == IP_MF)
printf("\t[      || More flagment     :: 0x%x ]\n", IP_MF);

else
printf("\t[      || Not support               ]\n");

printf("\t[        ========================== ]\n");
printf("\t[ Fragment Offset           :: %d ]\n", iph->ip_off);
printf("\t[           TTL             :: %d ]\n", iph->ip_ttl);
printf("\t[         Protocol          :: %d ]\n", iph->ip_p);
printf("\t[ Header Checksum           :: %d ]\n", iph->ip_sum);
printf("\t[ Source      IP address    :: %s ]\n", inet_ntoa(iph->ip_src));
printf("\t[ Destination IP address    :: %s ]\n", inet_ntoa(iph->ip_dst));
printf("\t-----------------------------------------  \n");

/* TCP Header analyze.
   Transport layer의 type을 알려주는 ip_p는 <netinet/ip.h>, IPPTORO_TCP의 내용은 <netinet/in.h> 참조. */
if (iph->ip_p == IPPROTO_TCP) {

tcph = (struct tcphdr *)(p + iph->ip_hl *4) ;

printf("\t\t[ TCP Packet!]\n");
printf("\t\t-----------------------------------------  \n");
printf("\t\t[ Source      Port :: %d ]\n", ntohs(tcph->source));
printf("\t\t[ Destination Port :: %d ]\n", ntohs(tcph->dest));
}

else if (iph->ip_p == IPPROTO_UDP) {

udph = (struct udphdr *)(p + iph->ip_hl *4) ;

printf("\t\t[ UDP Packet!]\n");
printf("\t\t-----------------------------------------  \n");
printf("\t\t[ Source      Port :: %d ]\n", ntohs(udph->source));
printf("\t\t[ Destination Port :: %d ]\n", ntohs(udph->dest));
}
}

else if(e_type == ETHERTYPE_ARP) {
printf("ARP!!!\n");
}

else if(e_type == ETHERTYPE_REVARP) {
printf("RARP!!!\n");
}

else {
printf("Not Captured packet!\n");
}

}

2013년 9월 29일 일요일

[MFC] MFC에서 UI Thread를 이용한 Dialog 호출 방법

==========================================================
출처 :
 http://blog.naver.com/PostView.nhn?blogId=aladdin07&logNo=150074142378&categoryNo=8&viewDate=&currentPage=1&listtype=0
==========================================================

1.목적
메인 프로그램에서 메뉴 항목을 선택하면 별도의 Dialog가 생성되어 거기서 정보를 입력 받는다.
단, 메인프로그램과 생성된 Dialog는 상호 독립적으로 구동되어야 한다.
(즉, 메인프로그램에서 DoModal()로 Dialog를 구동시키지 않고 별도 Thread로 구동 시켜야 한다)

2.방법
CWinThread Class를 활용한다.

① Class Wizard를 사용하여 CWinThread를 Base Class로하는 Class(CDlgThread)를 정의한다.
    Header File(DlgThread.h)에는 'DECLARE_DYNCREATE(CDlgThread);'
    Source File(DlgThread.cpp)에는 'IMPLEMENT_DYNCREATE(CDlgThread ,CWinThread)'
    ClassWizard에 의해 자동으로 추가됩니다.

DlgThread.h를 수정한다.
    - protected로 정의된 Constructor DlgThread()와 Deconstructor ~DlgThread()를 public으로
      바꾸어 준다. (이유는 해보면 안다)

      public:
           DlgThread();
           ~DlgThread();

③ Dialog 변수를 정의 한다.
    public:
         CDialog* m_pDlg;

④ CDlgThread의 InitInstance()에서 다음과 같이 독립실행 시킬 Dialog(CMyDlg)를 생성한다.
    이 작업은 Thread에 Dialog를 Binding 시키는 과정이다.
    BOOL CDlgThread::InitInstance()
    {
        m_pDlg = new CMyDlg();
        m_pDlg->ShowWindow( SW_SHOW );
        m_pDlg->UpdateWindow();
        return TRUE;
    }

⑤ CMyDlg Class의 Constructor를 수정한다.
    CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/)
         : CDialog(CMyDlg::IDD, pParent)
    {
        Create( IDD_MyDlg );    <== 요놈 추가
        //{{AFX_DATA_INIT(CDlgClub)
        // NOTE: the ClassWizard will add member initialization here
        //}}AFX_DATA_INIT
    }

⑥ 필요한 곳에서 다음과 같이하여 Thread를 구동 시키면 된다.

    CDlgThread*  m_pThread = new CDlgThread();
    m_pThread->CreateThread();

※ 상기와 같이하면 UI Thread를 구현할 수 있다..간단하죠~~잉..?
    위와 같이 구동된 Thread Dialog는 OK, CANCEL 버튼을 눌러도 소멸되지 않습니다.
    단지 HIDE 상태로 되는 거죠..
    따라서, 명시적으로 Thread Dialog를 죽이지 않았다면..메인 프로그램이 끝날때까지 Thread로
    남아 있게되는 거죠....요놈을 다시 사용하고 싶을때는 다음 두 줄로 다시 나타나게 만들면 된다.
    m_pThread->m_pDlg->ShowWindow( SW_SHOW );
    m_pThread->m_pDlg->UpdateWindow();
   
※ 명시적으로 Thread Dialog를 종료시킬려면 간단하다.
    Thread Dialog에 WM_QUIT Message를 보내면 된다.
    어떻게..?  PostThreadMessage()를 사용하면 된다.

    m_pThread->PostThreadMessage(WM_QUIT,0,0);

2013년 9월 28일 토요일

[WINPCAP] MFC로 pcap_findalldevs() 함수를 사용했는데 글자가 깨질때

========================================================
출처 : https://kldp.org/node/105221
========================================================












MFC에서 pcap_findalldevs()를 사용했는데 글자가 깨지는건 pcap_findalldevs() 함수가 사용하는 구조체 pcap_if가 가진 변수 name이 '유니코드'가 아닌 '멀티바이트' 형태로 저장하는데 현재 프로젝트가 유니코드로 설정 되어있어서라고 한다.




















위의 그림과 같이 '멀티바이트 문자 집합 사용'으로 바꾸면 아래와 같이
정상적으로 실행된다.



2013년 4월 24일 수요일

[wireshark] .PCAP 파일 포맷(File Format)


패킷 캡쳐시 리눅스 상에서는 Libpcap, 윈도우 상에서는 Winpcap 라이브러리를 사용하여 패킷을 수집할 경우, 확장자가 .PCAP이라는 파일 포맷(File Format)으로 처리된다.

그렇다면 .PCAP이라는 파일 포맷(File Format)은 어떤 모습일까??

아래의 그림과 같이 가장 처음으로 Global Header란 필드(Field)와 그 다음으로 Packet Header와 Packet Data란 필드(Field)가 한 쌍을 이루어 계속해서 나타나는 모습을 띄고 있다.


Global Header
Packet Header
Packet Data
Packet Header
Packet Data
Packet Header
Packet Data


그럼, 여기서 Global Header와 Packet Header, Packet Data란 무엇을 뜻하는 건지 알아보자.

========================================================

Global Header

typedef struct pcap_hdr_s {
        guint32 magic_number;   /* magic number */
        guint16 version_major;  /* major version number */
        guint16 version_minor;  /* minor version number */
        gint32  thiszone;       /* GMT to local correction */
        guint32 sigfigs;        /* accuracy of timestamps */
        guint32 snaplen;        /* max length of captured packets, in octets */
        guint32 network;        /* data link type */
} pcap_hdr_t;
Global Header는 libpcap file이라는 것을 나타내는 헤더이다. 
실제로 wireshark나 기타 프로그램에서 packet capture를 실행하여 실제로 패킷을 캡쳐한 후 확장자를 .pcap으로 저장하였을 경우 캡쳐한 패킷의 가장 처음 부분에 붙여지는 패킷 캡쳐시의 전체적인 정보이다.

Global Header의 전체 크기는 192bit, 즉 24byte이다.

Record (Packet) Header

typedef struct pcaprec_hdr_s {
        guint32 ts_sec;         /* timestamp seconds */
        guint32 ts_usec;        /* timestamp microseconds */
        guint32 incl_len;       /* number of octets of packet saved in file */
        guint32 orig_len;       /* actual length of packet */
} pcaprec_hdr_t;
Record (Packet) Header는 해당 패킷을 캡쳐했을 당시의 시간과 패킷 길이에 관한 정보로 이루어져 있다.

Record (Packet) Header의 전체 크기는 128bit, 즉 16byte이다.

============================================================================


Q_01. 그럼 Global Header와 Packet Header가 .pcap 파일의 가장 처음에 나오는 값들이라면 
          실제로 캡쳐한 최초 패킷의 데이터는 패킷의 어느위치에서부터 나오는 것인가?

Global Header와 Reacore (Packet) Header의 뒤를 이어 실제 캡쳐한 패킷에 대한 정보가 나오므로, 최초의 패킷 데이터는 Global Header + Packet Header의 크기만큼 이후부터 나오게 된다.
이후 Packet Data의 정보가 끝나면 그 다음 Packet Data에 대한 Packet Header가 새로 추가되어 하나의 쌍을 이루는 형태를 이루게 된다.



Global Header
Packet Header
Packet Data
Packet Header
Packet Data
Packet Header
Packet Data
...
 ----------------------------------------
 |       24byte      |      16byte       |      Packet Data 
 ----------------------------------------           = 실제 캡쳐한 패킷 정보
 | Global Header + Packet Header         (Ethernet 환경에서 캡쳐된 패킷이 대부분이기에 
 |                      => 40byte          |       Ethernet Protocol 정보로 시작된다고 보면 된다)



보통 우리가 쓰는 Internet 환경에서는 DataLink Layer Protocol을 Ethernet Protocol을 쓰기 때문에 Packet Header 부분 뒤에 나오는 Packet Data의 시작 부분에서는 Destination Hardware Address, 즉 목적지 맥주소가 나오게 된다.




실제로 .pcap 확장자로 저장한 캡쳐한 패킷 정보를 HxD 라는 헥사 에디터로 분석할 시 보여지는 16진수형 데이터들이다. 좌측에는 16진수 형태로, 그리고 우측에는 16진수에 해당하는 ASCII Code로 처리되어 보여지게 된다.

좌측에 보여지는 파란색으로 드래그 된 값들이 실제로 16진수로 표현된 Global Header와 최초로 캡쳐된 패킷과 쌍을 이루는 최초 패킷의 Packet Header에 대한 정보이다.

이후 나오는 값인 00 00 C0 9F A0 97 부터는 실제로 캡쳐된 패킷에 대한 정보들에 대한 값이다.


============================================================================

          2) 도서 : SECURITY 네트워크 패킷 포렌식 (최경철 지음, SECU BOOK)

============================================================================





spring에서 mariadb로 연동후 웹에서 접근시 jdbc 오류가 발생할때

* 본문은 [코드로 배우는 스프링 웹 프로젝트, 구멍가게 코딩단 지음] 도서를 공부하면서 정리한 글임을 밝힙니다.