반응형

 

 

https://www.x-plane.com/desktop/try-it/

 

Try It - X-Plane

The X-Plane 11 beta is here! Download the X-Plane 11 demo today, for free. Available for macOS, Windows, and Linux.

www.x-plane.com

 

 

https://www.flightgear.org/

 

FlightGear Flight Simulator – sophisticated, professional, open-source

Current stable release: 2020.3.18 – released 21/03/2023 This is our current well-tested and supported version for most users. Announcements 21st March 20202:  release 2020.3.18 is out. This includes an over-hauled generic autopilot and support for ortho

www.flightgear.org

 

반응형

"커널연구회"의 자료를 참고!

 

 

https://www.kernel.bz/blogPost/kernel-mov-list

 

커널 소스 분석 문서 및 동영상 강의 목록

 

kernel.bz

 

 

http://www.iamroot.org/

 

iamroot.org - IT 스터디

kernel, xen, kvm, gcc, ai 스터디 그룹

www.iamroot.org

 

 

http://www.iamroot.org/xe/index.php?mid=Study&document_srl=215076 

 

커널 스터디를 위한 문c 가이드입니다. - 스터디 - iamroot.org

안녕하세요? 문c 블로그(http://jake.dothome.co.kr)의 문영일입니다.   한 달 후면 여러분들이 1년간 기다리셨던 18차 커널 스터디가 시작됩니다. 커널 스터디를 통한 과실은 이미 많은 분들이 들어보

www.iamroot.org

 

 

http://jake.dothome.co.kr/

 

문c 블로그

최신 ARM 리눅스 5.x 커널 분석

jake.dothome.co.kr

 

 

 


 


https://hyeyoo.com/80

 

[kernel/locking] spinlock (1) - spinlock 사용법

앞선 글에서 lock이란 무엇이고, lock의 필요성에 대해서 알아보았다. 이번 글에서는 가장 기본적인 spinlock을 리눅스 커널에서 어떻게 구현했는지 알아볼 것이다. 우선 관련된 개념을 몇 가지 살펴

hyeyoo.com

 

 

https://pr0gr4m.github.io/

 

Linux Kernel Analysis

Linux Kernel Blog

pr0gr4m.github.io

 

반응형

 

 

 

참고 문서:
  "문c 블로그 - RCU(Read Copy Update)"
  http://jake.dothome.co.kr/rcu/

 

 

참고 문서: 
  "리눅스 커널 RCU 이해 / 커널연구회"
  https://kernel.bz/boardPost/118679/20

 

반응형

 

C language, Go(Golang), Netfilter, Netlink를 이용하여 Linux network을 제어하고 모니터링하는 방법을 알아보자~

 

 

개념 이해하기: Netfilter hooks into Linux networking packet flows

The following schematic shows packet flows through Linux networking:

 

From:  https://wiki.nftables.org/wiki-nftables/index.php/Netfilter_hooks

 

 


Linux Netfilter + C example code

참고 문서:   https://pr0gr4m.github.io/linux/kernel/netfilter/
  이론 설명과 함께 잘 동작하는 예시가 있어서 쉽게 이해할 수 있다.
  아래는 위 블로그의 끝 부분에 있는 HTTP Traffic만 선별하여 Drop하는 예제 코드인데,
  그냥 이 예제 코드만 봐도 이해할 수 있을 것이다.

 

http_netfilter.c

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/netdevice.h>

static unsigned int hook_http(void *priv,
		struct sk_buff *skb, const struct nf_hook_state *state)
{
	struct iphdr *iph;
	struct tcphdr *th;
	char *data = NULL;
	int length = 0;
	
	if (!skb)
		return NF_ACCEPT;

	iph = ip_hdr(skb);

	if (iph->protocol == IPPROTO_TCP) {
		th = tcp_hdr(skb);

		length = skb->len - iph->ihl * 4 - th->doff * 4;
		if (length <= 4)
			return NF_ACCEPT;

		data = kzalloc(length, GFP_KERNEL);
		memcpy(data, (unsigned char *)th + th->doff * 4, length);

		if (strstr(data, "HTTP") != NULL) {
			printk("[Kernel:%s] HTTP Detected\n", __func__);
			kfree(data);
			return NF_DROP;
		}

		kfree(data);
	}

	return NF_ACCEPT;
}

static struct nf_hook_ops *nf_ops = NULL;

static int __init nfilter_init(void)
{
	nf_ops = (struct nf_hook_ops *)kzalloc(sizeof(struct nf_hook_ops), GFP_KERNEL);
	nf_ops->hook = (nf_hookfn *)hook_http;
	nf_ops->pf = PF_INET;
	nf_ops->hooknum = NF_INET_LOCAL_IN;
	nf_ops->priority = NF_IP_PRI_FIRST;

	nf_register_net_hook(&init_net, nf_ops);
	printk("[Kernel:%s] NFilter Init\n", __func__);
	return 0;
}

static void __exit nfilter_exit(void)
{
	nf_unregister_net_hook(&init_net, nf_ops);
	kfree(nf_ops);
	printk("[Kernel:%s] NFilter Exit\n", __func__);
}

module_init(nfilter_init);
module_exit(nfilter_exit);
MODULE_LICENSE("GPL");

 

Makefile

obj-m += http_netfilter.o

KDIR := /lib/modules/$(shell uname -r)/build

default:
	$(MAKE) -C $(KDIR) M=$(PWD) modules

CC := gcc

%.c%:
	${CC} -o $@ $^

clean:
	$(MAKE) -C $(KDIR) M=$(PWD) clean
	rm -f ${TARGETS}

 

Build & Test

##
## HTTP Server 장비에서 아래 명령을 수행.
##

$ make

$ sudo insmod http_netfilter.ko

$


---

##
## 다른 PC에서 아래와 같이 HTTP Traffic을 발생시켜본다.
##
$ curl -v http://my-test.server.domain/

*   Trying my-test.server.domain:80...
* Connected to my-test.server.domain port 80 (#0)
> GET / HTTP/1.1
> Host: my-test.server.domain
> User-Agent: curl/7.77.0
> Accept: */*
> ##
## TCP Session만 수립될 뿐, 
## 실제 HTTP Response 패킷을 받지 못해서 이 상태로 계속 남아있다가 Timed out 처리된다.
##
* Recv failure: Operation timed out
* Closing connection 0
curl: (56) Recv failure: Operation timed out
$


---

##
## HTTP Server 장비에서 아래 명령을 수행.
##

$ dmesg --color --follow
... 중간 생략 ..
[264707.035282] [Kernel:hook_http] HTTP Detected
[264711.387549] [Kernel:hook_http] HTTP Detected
... 중간 생략 ..

 

 

 

 

 

 


Netlink for C language

Wikipedia

Netlink Protocol Library Suite (libnl)

Core Library Developer's Guide (libnl)

Routing Library Developer's Guide (libnl-route)

Example Collection

 

 

 

위 문서를 읽고 나서, 아래 예제를 테스트하면서 이해하기.

$  cat detect_chg_event.c


/**
 * How to build
 *   $  gcc -o detect_chg_event detect_chg_event.c
 * How to run
 *   $  ./detect_chg_event
 */

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <netdb.h>
#include <netinet/in.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>


static int
create_sock (const char *nic)
{
    struct sockaddr_nl addr;
    int                sock;

    memset (&addr, 0, sizeof (addr));
    addr.nl_family = AF_NETLINK;
    addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR;

    sock = socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (sock < 0)
    {
        fprintf (stderr, "failed to open NETLINK_ROUTE socket for %s - %s(%d)",
                nic, strerror (errno), errno);
        return -1;
    }

    if (bind (sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        fprintf (stderr, "failed to bind NETLINK_ROUTE socket for %s - %s(%d)",
                nic, strerror (errno), errno);
        close (sock);
        return -1;
    }

    return sock;
}


/**
 * NOTE: Cheeck if NIC status is changed
 */
static int
ip_changed (int         sock,
			const char *nic)
{
    struct nlmsghdr   *nlh;
    char               buffer[4096];
    int                len;
    int                idx;
    int                found;

    len = recv (sock, buffer, sizeof (buffer), 0);
    if (len <= 0)
    {
        fprintf (stderr, "NETLINK_ROUTE socket recv() failedn");
        return -1;
    }

    printf("\n %s %s(%d) Receive message from raw socket \n",
            __func__, __FILE__, __LINE__);

    found = 0;
    idx = if_nametoindex (nic);

    printf("\n %s %s(%d) Index of %s: %d \n",
            __func__, __FILE__, __LINE__, nic, idx);

    for (	nlh = (struct nlmsghdr *) buffer;
            NLMSG_OK (nlh, len);
            nlh = NLMSG_NEXT (nlh, len))
    {
        if (nlh->nlmsg_type == NLMSG_DONE)
            break;
        if (nlh->nlmsg_type == NLMSG_ERROR)
            continue;
        if (!(NLMSG_OK (nlh, len)))
            continue;

        printf("\n %s %s(%d) Netlink MSG Type: %d\n",
                __func__, __FILE__, __LINE__, nlh->nlmsg_type);

        /*
         * NOTE:
         *   RTM_NEWADDR, RTM_NEWLINK 에 관한 정의는 rtnetlink.h 파일에서 확인할 수 있다.
         *     - /usr/include/linux/rtnetlink.h
         */
        switch (nlh->nlmsg_type)
        {
            case RTM_NEWADDR:
                {
                    struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA (nlh);

                    if (ifa->ifa_index == idx)
                        found = 1;
                }
                break;
            case RTM_NEWLINK:
                {
                    struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA (nlh);

                    if (ifi->ifi_index == idx)
                        found = 1;
                }
                break;
            default:
                break;
        }
    }

    return found;
}


static int
get_nic_addr (  const char     *nic,
				struct ifaddrs *ifaddr,
				int             wanted_family,
				char           *host,
				int             host_len,
				int            *active)
{
    struct ifaddrs *ifa;

    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
    {
        int family;
        int s;

        if (ifa->ifa_addr == NULL)
            continue;

        if (strcmp (ifa->ifa_name, nic))
            continue;

        /* Skip unwanted families. */
        family = ifa->ifa_addr->sa_family;
        if (family != wanted_family)
            continue;

        *active = (ifa->ifa_flags & IFF_RUNNING) ? 1 : 0;

        s = getnameinfo (   ifa->ifa_addr,
                            family == AF_INET ? sizeof (struct sockaddr_in) :
                            sizeof (struct sockaddr_in6),
                            host,
                            host_len,
                            NULL,
                            0,
                            NI_NUMERICHOST);
        if (s != 0)
        {
            fprintf (stderr, "failed to getnameinfo() for '%s - %s(%d)",
                    ifa->ifa_name, strerror (errno), errno);
            continue;
        }

        /* Get the address of only the first network interface card. */
        return 1;
    }

    return 0;
}


static void
print_ip (const char *nic)
{
    struct ifaddrs *ifaddr;
    char            addr[NI_MAXHOST];
    int             active;

    printf("\n %s(%d) nic: %s \n",
            __FILE__, __LINE__, nic);

    if (getifaddrs (&ifaddr) == -1)
    {
        fprintf (stderr, "failed to getifaddrs() - %s(%d)", strerror (errno), errno);
        return;
    }

    // NOTE: IPv4
    if (!get_nic_addr (nic, ifaddr, AF_INET, addr, sizeof (addr), &active))
    {
        // If IPv4 configuration is not available,
        // then try to get the Ipv6 configuration.
        printf("\n %s(%d) nic: %s  addr: %s  active: %d \n",
                __FILE__, __LINE__, nic, addr, active);
        // NOTE: IPv6
        if (!get_nic_addr (nic, ifaddr, AF_INET6, addr, sizeof (addr), &active))
        {
            // Nothing to do.
            strcpy (addr, "127.0.0.1");
            active = 0;
        }
    } else {
        printf("\n %s(%d) nic: %s  addr: %s  active: %d \n",
                __FILE__, __LINE__, nic, addr, active);
    }

    freeifaddrs (ifaddr);

    printf("\n %s %s(%d) %s is %s (link %s) \n",
            __func__, __FILE__, __LINE__,
            nic, addr, active ? "active" : "inactive");
}


int
main (void)
{
    // FIXME: enp7s0 --> my machine's network interface name
    char *nic = "enp7s0";
    int   sock;

    print_ip (nic);

    sock = create_sock (nic);
    if (sock < 0)
        return -1;

    while (1)
    {
        int ret;

        ret = ip_changed (sock, nic);
        if (ret < 0)
            return -1;

        if (ret)
            print_ip (nic);

        printf("\n\n %s %s(%d) END OF LOOP \n\n\n",
                __func__, __FILE__, __LINE__);
    }

    close (sock);

    return 0;
}


$

$  gcc -o detect_chg_event detect_chg_event.c

$  ./detect_chg_event

ip_changed detect_chg_event.c(73) Receive message from raw socket

 ip_changed detect_chg_event.c(79) Index of enp7s0: 2

 ip_changed detect_chg_event.c(93) Netlink MSG Type: 16

 detect_chg_event.c(181) nic: enp7s0

 detect_chg_event.c(205) nic: enp7s0  addr: 10.1.4.51  active: 1

 print_ip detect_chg_event.c(211) enp7s0 is 10.1.4.51 (link active)


 main detect_chg_event.c(239) END OF LOOP
 
 ...
 ...

 

위 예제에서 detect_chg_event 명령을 실행시켜 놓고, 아래와 같이 명령을 실행해본다.

$  ifconfig  enp7s0  mtu 1501
$  ifconfig  enp7s0  mtu 1500
$  ifconfig  enp7s0  down
$  ifconfig  enp7s0  up

detect_chg_event 예제 앱이 enp7s0 장치의 상태 변화를 감지해서 터미널에 감지한 내용을 출력해줄 것이다.

 

Netlink library for go

https://github.com/vishvananda/netlink

 

 


 

 

https://tomdnetto.net/post/linux_networking_from_go_nftables

 

Linux Networking From Go

Manipulating network interfaces, firewalling, and forwarding from Go.

tomdnetto.net

 

 

https://tomdnetto.net/post/advanced_nftables_with_go

 

Advanced NFTables With Go

NFTables like your mama taught you.

tomdnetto.net

 

 

 

반응형

 


 

작성일: 2023년 7월 16일
IPv6 스터디하면서 참고했던 자료나 기억할 것을 여기에 기록하기

 

IPv6 주소 표기

IPv6 주소 표기

  • 128 bit
  • 16 bit 씩 8자리로 구성. 각 자리는 콜론으로 구분
  • 앞 64 bit는 network address, 뒤 64 bit는 장비의 network interface address
    (network address는 64 bit 길이가 아니어도 된다. 더 크거나 더 작아도 된다.)
  • IPv6 주소 예시
2001:db8:0:1::a00:1
2001:db8:0:1::a00:1/64

 

IPv4, IPv6 Header 구조 비교

IPv4, IPv6 Header 구조 비교

 

IPv6 확장 Header

 

IPv6 확장 Header

 

IPv6 통신 방식 (Network Node 간 통신 방식)

IPv6 통신 방식 Description
Unicast 1:1 통신 (특정 1개 Node간 통신)
Multicast 1:N 또는 N:M 노드간 통신
Anycast 전세계에 동일한 Anycast address를 가진 node 중에서 가장 통신 cost가 적게 되는 node를 선택하여 통신

 

 

IPv6 주소 종류

IPv6 Address Types

Unicast Address 종류

Unicast Address 종류 Description
Global Unicast Address - Public IP Address
- IPv4에 비유하자면 Public IP address 같은 용도로 사용하는 IPv6 address
- 2000::/3
- 각 기관별 IPv6 할당 가능한 주소 값을 아래 할당 표를 열람
   https://www.iana.org/assignments/ipv6-unicast-address-assignments/ipv6-unicast-address-assignments.xhtml
- 국내 IPv6 관리 대행자별 IPv6 주소 목록
   https://krnic.kisa.or.kr/jsp/business/management/isCurrentIpv6.jsp

Link-Local Unicast Address - Link 내에서만 사용 가능한 Address.
- 예를 들어, Router-A가 Link-Local Unicast Address를 Destination Address로 하는 패킷을 받으면 다른 Network로 Forward하지 않는다.
- 그래서 1개 Link 구간에서 Network control message를 전달할 때, 이 주소를 사용한다.
- 만약, 1개 물리적 포트에 Global Unicast Address와 Link-Local Unicast Address를 모두 설정한 경우라면 Global Unicast Address 값을 변경하는 경우에도 Link-Local Unicast Address로 통신이 가능하다.
- 1개 Link 내에서만 통신이 가능하기 때문에 ICMPv6를 이용한 외부에서의 공격을 원천적으로 막을 수 있다.
- IPv4의 자동 설정 IP 주소인 169.254.x.x에 유사한 목적으로 사용됨
- FE80::/10
Unique Local Unicast Address - IPv4에 비유하자면 Private network address(10.0.0.0 172.16.0.0 192.168.0.0) 같은 IPv6 address.
- 예를 들어, 1개 회사 빌딩 내부에서의 통신, 1개 대학 캠퍼스 내부에서의 통신만 할 때 이 주소를 사용한다.
- FC00::/7

예시: Global Unicast Address

(예시) Global Unicast Address

예시: Link Local Unicast Address

(예시) Link Local Unicast Address

 

Multicast Address

ff00::/8 - IPv6 멀티캐스트를 위한 주소공간이다. IPv4에서 제공했던 브로드캐스트는 IPv6에서는 더 이상 지원되지 않으며, IPv6에서는 대신 멀티캐스트를 사용해야 한다.

Multicast Address 종류 Description
Solicited Node Multicast - 이더넷 환경에서 Neighbor 탐색 과정(IPv4의 ARP 과정과 유사)에 사용
Auto configuration 과정에서 DAD(Duplicate Address Detection) 과정을 거칠 때 사용
- Solicited Node Multicast 주소의 112비트 부분은 FF02::1:FF로 정해져 있으며 나머지 24비트는 IPv6의 최하위 24비트 부분을 차용하여 사용
(예: IPv6 주소-2001:1:1:1::1234:5678 → Solicited node multicast 주소- FF02::1:FF34:5678)
All Node Multicast - 노드의 모든 IPv6 호스트와 라우터들이 소속되어 있는 그룹
- All node multicast주소는 FF02::1 사용
All Router Multicast 모든 IPv6 라우터들이 소속되어 있는 그룹
- All router multicast 주소는 FF02::2 사용

IPv6 Multicast Group

IPv6 Multicast Group

 

Anycast Address

Anycast 통신은 ‘1:가장 가까운 1’간의 통신방식이라고 정의할 수 있다.

동일한 주소를 가지는 여러 목적지 장비들 중 출발지 장비와 가장 가까운 장비가 응답을 하는 통신방식이다.
이러한 통신방식은 멀티캐스트와 유사하지만 멀티캐스트의 경우 동일 그룹에 소속된 장비들이 응답을 하는 반면, 애니캐스트의 경우는 동일 주소를 가지는 장비들 중 가장 가까운 장비 하나만 응답을 한다는 차이가 있다.

 

IPv4-mapped IPv6 addresses

주소 표현 예시 ::FFFF:129.144.52.38
명령 사용 예시 $  ping ::ffff:192.168.139.50
$  ping ::ffff:c0a8:8b32

 

IPv6 Address Scope 개념

IPv6 Address Scope 종류 Description
Global Scope IPv6로 통신할 수 있는 모든 영역 (예: 지구 전체)
Link-Local Scope Broadcast domain 또는 Network interface가 직접 연결된 Link 영역
Site-Local Scope [ 내 생각:  실제로 이 Site-Local Scope 개념이 사용되는지 모르겠음 ]

[ 내 생각:  Site-Local Address는 2004년 10월 RFC3897에서 폐기되었음. 아마 Site-Local Scope의 모호성 때문에 폐기한 것이 아닌가 추정해봄 ]

한 조직의 관리자가 관리하는 Network 영역 (예: 특정 통신사, 회사, 호텔, 정부청사 같은 영역)
네트워크 관리자가 Site-Local Scope을 설정하는 것이므로 Scope의 경계를 설명하기 애매하다.
예를 들어, 네트워크 관리자가 A회사와 B호텔을 1개의 Site-Local Scope으로 지정하면,
의도하지 않게 Networking이 되는 상황이 발생

 

 

국내 IPv6 관리대행자별 IPv6 주소 목록 (2023.07.17 현재)

기관명 영문서비스명 시작주소 프리픽스 개수 할당일
에이비클 ABCLE 2001:0EF8:: /32 65536 20040524
(주)아프리카티비 AFREECATV 2406:6600:: /32 65536 20110124
(주)엘지유플러스 BORANET 2001:0270:: /32 65536 20000908
씨디네트웍스 CDNETWORKS 2401:C500:: /32 65536 20110830
(주) 씨엠비 CMBI-NETDJ 2403:6500:: /32 65536 20120326
주식회사 씨엠비영등포방송 CMBI-NETHK 2404:2300:: /32 65536 20120607
주식회사 씨엠비광주방송 CMBKWANGJUNET 2406:B000:: /32 65536 20080324
주식회사 씨엠비광주방송 CMBKWANGJUNET 2402:7000:: /32 65536 20080403
(주)다우기술 DAOU 2403:3E00:: /32 65536 20100707
디지털엣지코리아 DEK-NET 2400:FD60:: /32 65536 20230512
삼정데이타서비스(주) DIRECT-HOSTING 2403:3700:: /32 65536 20120307
주식회사 딜라이브 DLIVE 2402:BE00:: /32 65536 20100608
드림라인(주) DREAMX 2001:0C48:: /32 65536 20020812
두루안 DURUAN 2001:0390:: /32 65536 20020207
(주)이호스트아이씨티 EHOSTICT 2407:0B00:: /32 65536 20130529
(주)가비아 GABIA-IP 2401:9EC0:: /32 65536 20170811
한국케이블TV푸른방송(주) GCS 2407:2000:: /32 65536 20070716
엔티티코리아 주식회사 GIN 2001:0D38:: /32 65536 20030515
하이온넷(주) HAIONNET 2404:0800:: /32 65536 20080912
주식회사 에이치씨엔 HCN 2001:0EA0:: /32 65536 20040329
주식회사 하이라인닷넷 HINETWORKS 2407:B200:: /32 65536 20110314
호스트웨이아이디씨(주) HOSTWAY 2406:AD00:: /32 65536 20130410
효성ITX HYOSUNGCDN 2407:3500:: /32 65536 20130618
인천국제공항공사 IIAC 2400:A0A0:: /32 65536 20220816
주식회사 아이네트호스팅 INET 2001:0F48:: /32 65536 20040806
JCN울산중앙방송(주) JCN 2402:1A00:: /32 65536 20100506
주식회사 제이엔디통신 JNDINFO 2402:6100:: /32 65536 20111101
금강방송주식회사 KCNNET 2403:6300:: /32 65536 20120326
한국데이타 KDATA 2406:6800:: /32 65536 20090402
(주)한국데이터통신 KDTIDC 2405:3500:: /32 65536 20120921
(주)엘지유플러스 KIDC 2001:0ED0:: /32 65536 20040418
주식회사 케이아이엔엑스 KINXINC 2001:07FA:0008:: /48 1 20020402
주식회사 케이아이엔엑스 KINXINC 2401:2700:: /32 65536 20110615
한국지능정보사회진흥원 KOREN 2407:C000:: /32 65536 20070522
한국지능정보사회진흥원 KOREN 2406:D000:: /32 65536 20080204
주식회사 케이티 KORNET 2001:0220:: /32 65536 19991006
주식회사 케이티 KORNET 2001:0280:: /32 65536 20000927
주식회사 케이티 KORNET 2001:02B0:: /32 65536 20010102
주식회사 케이티 KORNET 2001:0E60:: /32 65536 20040213
주식회사 케이티 KORNET 2001:0EA8:: /32 65536 20040331
주식회사 케이티 KORNET 2001:0EF0:: /32 65536 20040524
주식회사 케이티 KORNET 2400:0000:: /20 268435456 20050601
재단법인 한국교육전산망협의회 KREN 2001:0E70:: /32 65536 20040317
재단법인 한국교육전산망협의회 KREN 2402:0000:: /22 67108864 20061107
한국과학기술정보연구원 KREONet 2001:0320:: /32 65536 20010823
(주)한국무역정보통신 KTNET 2001:0EB8:: /32 65536 20040407
주식회사 엘지헬로비전 LG-HELLOVISION 2405:7B00:: /32 65536 20121017
(주) 엘지씨엔에스 LG-NET 2400:3300:: /32 65536 20110407
(주)엘지유플러스 LGTELECOM 2001:4430:: /32 65536 20050706
엘엑스(IP주소 인터넷 서비스 업체) LXN 2402:3100:: /32 65536 20111012
네이버클라우드 주식회사 NBP-NET 2402:DE00:: /32 65536 20110107
(주)비트넷 NETIP 2405:5F00:: /32 65536 20121010
엔에이치엔클라우드 NHNCLOUD-NET 2405:D880:: /32 65536 20160630
남인천방송(주) NIBDIGITAL 2407:B800:: /32 65536 20090520
피란하시스템즈 PIRANHA 2402:F400:: /32 65536 20100113
(주)엘지유플러스 PUBNETPLUS 2001:0E78:: /32 65536 20040317
삼성에스디에스(주) SAMSUNGSDS 2001:0330:: /32 65536 20010920
삼성에스디에스(주) SAMSUNGSDS 2404:0180:: /28 1048576 20060829
(주)에스비코리아 SBKOREACORP 2400:FDA6:: /32 65536 20230512
세종텔레콤 주식회사 SHINBIRO 2001:03A8:: /32 65536 20020402
세종텔레콤 주식회사 SHINBIRO 2001:0CF0:: /32 65536 20030122
SK(주) SK-NET 2405:8600:: /32 65536 20101202
에스케이텔레콤(주) SK-TELECOM-NET 2001:02D8:: /32 65536 20010406
에스케이텔레콤(주) SK-TELECOM-NET 2001:0F28:: /32 65536 20040708
에스케이텔링크주식회사 SKTelink 2001:0E98:: /32 65536 20040329
케이디디아이코리아(주) TELEHOUSE-SEOUL 2400:1800:: /32 65536 20090128
유엘네트웍스 ULNETWORKS 2405:4300:: /32 65536 20120925
주식회사 넥스지 VAAN 2402:5800:: /32 65536 20080703
주식회사 브이토피아 VTOPIA 2406:D700:: /32 65536 20130502
(주)엘지유플러스 Xpeed 2406:5900:: /32 65536 20130306
에스케이브로드밴드주식회사 broadNnet 2001:0290:: /32 65536 20001030
에스케이브로드밴드주식회사 broadNnet 2001:0378:: /32 65536 20011218
에스케이브로드밴드주식회사 broadNnet 2001:0EE8:: /32 65536 20040517
에스케이브로드밴드주식회사 broadNnet 2001:44D0:: /28 1048576 20051110
에스케이브로드밴드주식회사 broadNnet 2401:4000:: /32 65536 20070316
에스케이브로드밴드주식회사 broadNnet 2406:4000:: /32 65536 20070316
에스케이브로드밴드주식회사 broadNnet 2401:A800:: /32 65536 20080602
에스케이브로드밴드주식회사 broadNnet 2405:5800:: /32 65536 20081020
에스케이브로드밴드주식회사 broadNnet 2407:6500:: /32 65536 20130705
에스케이브로드밴드주식회사 broadNnet 2407:6700:: /32 65536 20130705
에스케이브로드밴드주식회사 broadNnet 2407:9100:: /32 65536 20130718
에스케이브로드밴드주식회사 broadNnet 2407:C700:: /32 65536 20130822
에스케이브로드밴드주식회사 broadNnet 2400:4980:: /32 65536 20131106
에스케이브로드밴드주식회사 broadNnet 2400:4780:: /32 65536 20131111
에스케이브로드밴드주식회사 broadNnet 2400:9E80:: /32 65536 20140213
에스케이브로드밴드주식회사 broadNnet 2400:9F80:: /32 65536 20140213
에스케이브로드밴드주식회사 broadNnet 2400:A580:: /32 65536 20140218
에스케이브로드밴드주식회사 broadNnet 2400:E180:: /32 65536 20140415
(주)이지오스 eGIOSNET 2405:C000:: /32 65536 20070509

 


 

Linux (Ubuntu)에서 IPv6 Address 사용

IPv6 Address 설정하기 (nmcli 명령 사용)

## ip addr 명령으로 설정
##   a) IPv6 주소 설정
$ ip -6 addr add 2001:db8:0:1::a00:2/64 dev enp1s0

##   b) IPv6 주소 삭제
$ ip -6 addr del 2001:db8:0:1::a00:2/64 dev enp1s0

##   c) IPv6 주소 확인
$ ip -6 addr show dev enp1s0


## nmcli 명령으로 설정
##   a) Network device list 출력
$  nmcli  dev

##   b) IPv6 주소 설정
$ nmcli  con  mod  ens0  ipv6.address 2001:db8:0:1::a00:1/64  ipv6.gateway 2001:db8:0:1::1

 

참고 문서   https://www.lesstif.com/system-admin/centos-nmcli-ip-static-ip-98926807.html

 

 

IPv6 Address 설정하기 (Gnome GUI 설정 화면 사용)

아래 예시 화면처럼 [IPv6] 설정 탭에서 Address, Prefix, Gateway를 설정한다.

IPv6 설정 GUI 화면

 

 

 

Web Browser로 IPv6 주소의 웹 페이지 조회하기

아래 예제처럼 주소창에 IPv6 주소값을 입력하고 테스트해본다.

http://[2001:db8:0:1::a00:1]:8080/

IPv6 주소의 웹페이지 조회

 

curl 명령으로 동일하게 테스트할 수 있다. (아래 예제를 참고)

$  curl http://[2001:db8:0:1::a00:1]:8080/

 Hello from example application. (written by Andrew)

$

 

 

 

CURL 명령으로 IPv6 주소 확인하기 (Global scope address)

## 이 장비의 Network port에 설정된 IPv6 주소 열람하기
$  ip -6 addr

## IPv6 주소 중에서 Global scope 주소만 열람하기
$  ip -6 addr show scope global 

## 나의 NAT 장비의 IPv6 인터넷 주소 확인하기
## (참고: NAT에 IPv6가 설정되지 않았으면, IPv4 주소가 출력된다)
$  dig -6 TXT +short o-o.myaddr.l.google.com @ns1.google.com

$  dig -t aaaa +short myip.opendns.com @resolver1.opendns.com

$  curl -6 https://ifconfig.co

$  curl -6 https://ipv6.icanhazip.com  

$  ssh -6 sshmyip.com

 

 

 

 

 

IPv4 to IPv6 주소 변환하기

IPv4 Address to IPv6 Address Conversion | IPAddressGuide
IPv4 to IPv6 Conversion



 


 

 

참고 문서:
  KRNIC 스터디 자료 
    https://xn--3e0bx5euxnjje69i70af08bea817g.xn--3e0b707e/jsp/resources/vsix/icmp.jsp
  NDP 설명 영상
    https://www.youtube.com/watch?v=A3LFt7CHpgs
  https://www.minzkn.com/moniwiki/wiki.php/IPv6
  https://en.wikipedia.org/wiki/IPv6_address

 

 

반응형

아래 예시는 Linux OS에 Hugepage를 적용하는 절차이다.

##
## /etc/default/grub 파일에서  
## default_hugepagesz, hugepagesz, hugepages, transparent_hugepage
## 항목을 추가 설정한다.
## (아래 예시를 참고)
##

$ cat  /etc/default/grub

GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet default_hugepagesz=1GB hugepagesz=1G hugepages=320 transparent_hugepage=never"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true

$

##
## 위와 같이 /etc/default/grub 파일을 수정하고,
## grub2 명령으로 설정을 적용한다.
##

## Case: UEFI Mode
$ grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg

## Case: Legacy BIOS Mode
$ grub2-mkconfig -o /boot/grub2/grub.cfg

##
## 위와 같이 설정 작업을 마무리했으면, OS를 Reboot하여 설정을 반영한다.
##

$ reboot
반응형

Go Language로 특정 Process의 CPU, Memory 사용량을 계산하고 싶다면,

아래의 코드를 Build해서 사용하면 된다.

 

참고: Linux, MacOS, Unix, Windows 모두 동작하는 코드임.

 

 

// Filename: proc_usage.go

package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"math"
	"os/exec"
	"path"
	"runtime"
	"strconv"
	"strings"
	"sync"
)

const (
	statTypePS   = "ps"
	statTypeProc = "proc"
)

// SysInfo will record cpu and memory data
type SysInfo struct {
	CPU    float64
	Memory float64
}

// Stat will store CPU time struct
type Stat struct {
	utime  float64
	stime  float64
	cutime float64
	cstime float64
	start  float64
	rss    float64
	uptime float64
}

type fn func(int) (*SysInfo, error)

var fnMap map[string]fn
var platform string
var history map[int]Stat
var historyLock sync.Mutex
var eol string

// Linux platform
var clkTck float64 = 100    // default
var pageSize float64 = 4096 // default

func init() {
	platform = runtime.GOOS
	if eol = "\n"; strings.Index(platform, "win") == 0 {
		platform = "win"
		eol = "\r\n"
	}
	history = make(map[int]Stat)
	fnMap = make(map[string]fn)
	fnMap["darwin"] = wrapper("ps")
	fnMap["sunos"] = wrapper("ps")
	fnMap["freebsd"] = wrapper("ps")
	fnMap["openbsd"] = wrapper("proc")
	fnMap["aix"] = wrapper("ps")
	fnMap["linux"] = wrapper("proc")
	fnMap["netbsd"] = wrapper("proc")
	fnMap["win"] = wrapper("win")

	if platform == "linux" || platform == "netbsd" || platform == "openbsd" {
		initProc()
	}
}

func initProc() {
	clkTckStdout, err := exec.Command("getconf", "CLK_TCK").Output()
	if err == nil {
		clkTck = parseFloat(formatStdOut(clkTckStdout, 0)[0])
	}

	pageSizeStdout, err := exec.Command("getconf", "PAGESIZE").Output()
	if err == nil {
		pageSize = parseFloat(formatStdOut(pageSizeStdout, 0)[0])
	}

}

func wrapper(statType string) func(pid int) (*SysInfo, error) {
	return func(pid int) (*SysInfo, error) {
		return stat(pid, statType)
	}
}

func formatStdOut(stdout []byte, userfulIndex int) []string {
	infoArr := strings.Split(string(stdout), eol)[userfulIndex]
	ret := strings.Fields(infoArr)
	return ret
}

func parseFloat(val string) float64 {
	floatVal, _ := strconv.ParseFloat(val, 64)
	return floatVal
}

func statFromPS(pid int) (*SysInfo, error) {
	sysInfo := &SysInfo{}
	args := "-o pcpu,rss -p"
	if platform == "aix" {
		args = "-o pcpu,rssize -p"
	}
	stdout, _ := exec.Command("ps", args, strconv.Itoa(pid)).Output()
	ret := formatStdOut(stdout, 1)
	if len(ret) == 0 {
		return sysInfo, errors.New("Can't find process with this PID: " + strconv.Itoa(pid))
	}
	sysInfo.CPU = parseFloat(ret[0])
	sysInfo.Memory = parseFloat(ret[1]) * 1024
	return sysInfo, nil
}

func statFromProc(pid int) (*SysInfo, error) {
	sysInfo := &SysInfo{}
	uptimeFileBytes, err := ioutil.ReadFile(path.Join("/proc", "uptime"))
	if err != nil {
		return nil, err
	}
	uptime := parseFloat(strings.Split(string(uptimeFileBytes), " ")[0])

	procStatFileBytes, err := ioutil.ReadFile(path.Join("/proc", strconv.Itoa(pid), "stat"))
	if err != nil {
		return nil, err
	}
	splitAfter := strings.SplitAfter(string(procStatFileBytes), ")")

	if len(splitAfter) == 0 || len(splitAfter) == 1 {
		return sysInfo, errors.New("Can't find process with this PID: " + strconv.Itoa(pid))
	}
	infos := strings.Split(splitAfter[1], " ")
	stat := &Stat{
		utime:  parseFloat(infos[12]),
		stime:  parseFloat(infos[13]),
		cutime: parseFloat(infos[14]),
		cstime: parseFloat(infos[15]),
		start:  parseFloat(infos[20]) / clkTck,
		rss:    parseFloat(infos[22]),
		uptime: uptime,
	}

	_stime := 0.0
	_utime := 0.0

	historyLock.Lock()
	defer historyLock.Unlock()

	_history := history[pid]

	if _history.stime != 0 {
		_stime = _history.stime
	}

	if _history.utime != 0 {
		_utime = _history.utime
	}
	total := stat.stime - _stime + stat.utime - _utime
	total = total / clkTck

	seconds := stat.start - uptime
	if _history.uptime != 0 {
		seconds = uptime - _history.uptime
	}

	seconds = math.Abs(seconds)
	if seconds == 0 {
		seconds = 1
	}

	history[pid] = *stat
	sysInfo.CPU = (total / seconds) * 100
	sysInfo.Memory = stat.rss * pageSize
	return sysInfo, nil
}

func stat(pid int, statType string) (*SysInfo, error) {
	switch statType {
	case statTypePS:
		return statFromPS(pid)
	case statTypeProc:
		return statFromProc(pid)
	default:
		return nil, fmt.Errorf("Unsupported OS %s", runtime.GOOS)
	}
}

// GetStat will return current system CPU and memory data
func GetStat(pid int) (*SysInfo, error) {
	sysInfo, err := fnMap[platform](pid)
	return sysInfo, err
}

 

 

 

// Filename: main.go

package main

import (
    "os"
    "fmt"
    "time"
    "strconv"
)

func main() {
    myPid, _ := strconv.Atoi(os.Args[1])

    for i:= 0; i < 100; i++ {
        sysInfo, _ := GetStat(myPid)
        fmt.Println("CPU Usage     :", sysInfo.CPU)
        fmt.Println("Mem Usage(RSS):", sysInfo.Memory)
        time.Sleep(5 * time.Second)
    }
}

 

위와 같이 Go source code를 모두 작성했다면, 아래처럼 build하고 실행하면 된다.

 

$ go mod init andrew.space/proc_usage
go: creating new go.mod: module andrew.space/proc_usage
go: to add module requirements and sums:
	go mod tidy
    
$ go mod tidy

$ go build

$ ./proc_usage 4314
CPU Usage     : 52.92167225853122
Mem Usage(RSS): 2.018664448e+09
CPU Usage     : 39.800000000000004
Mem Usage(RSS): 2.018664448e+09
CPU Usage     : 47.30538922366738
Mem Usage(RSS): 2.018664448e+09
...
...

 

top 명령으로 본 것과 결과가 동일했다.

반응형

시스템 알람을 발생시키는 테스트를 하거나 Kubernetes의 Horizontal Pod Autoscaler 기능 테스트를 할 때,

CPU 부하를 발생시키는 명령 도구가 있으면 편하다.

아래와 같이 설치하고 테스트하면 된다. (설명은 생략하고, 그냥 따라해보자~)

 

##
## 설치
##

$ yum install -y stress

$ stress --help
...

##
## 30초 동안 3000ms의 CPU 과부하를 유발하기.
##
$ stress --cpu 3 --timeout 30s

##
## 500MB의 메모리 과부하를 유발하기
##  --vm : Worker 개수
##  --vm-hang : malloc 실행 후 free하기 전까지 sleep할 시간(초)
##
$ stress --vm 1 --vm-bytes 500M --vm-hang 1

 

블로그 작성자: sejong.jeonjo@gmail.com

 

 

+ Recent posts