블로그 이미지
바람이 바뀌는 곳... 박영창

카테고리

왠 또라이의 세상살.. (1267)
원래 여기가 이런곳.. (584)
아마 좋아하는 듯... (464)
나를 싫어하는 놈들.. (109)
먹고는 살아야지;;; (48)
그땐 그랬지 :-) (29)
걷다보니 여기까지... (23)
Total789,070
Today258
Yesterday287
 요즘 회사에서 인터넷을 사용하는데 방화벽(+기타등등)의 보안툴로 점점 네트워크를 사용하는게 힘들어지면서 찾기 시작한 VPN서버를 이용한 터널링을 설정해보기로 했다. 서버로 이용하는 것은 예전에 학교에서 활동하던 학회에서 사용하는 서버이며, 일반적으로 많이들 사용하는 우분투 기반의 서버이다. (우분투이니 데비안에는 그냥 적용 가능할 것이라고 생각함)

 상대적으로 openvpn 서버를 이용하지 않고, 윈도우에서 사용하는 pptp 프로토콜을 사용하려고 하는 경우 poptop의 우분투 패키지인 pptpd 를 설치하고 간단한 설정을 통해서 바로 접속이 가능했다. 문제는 우리 회사의 경우 pptpd 를 정책상 막아 놓은건지 서버로 접속은 가능했지만, 서버에서 외부 접속에서 사용하는 ppp를 생성하는 중에 아래와 같은 메시지를 뿜으면서 커넥션을 잃어버리더라...

pptpd 설정



root@zeropage:/var/lib/mysql# tail -f /var/log/syslog
...
Nov 23 16:28:21 zeropage pptpd[7279]: CTRL: Client 203.244.218.56 control connection started
Nov 23 16:28:21 zeropage pptpd[7279]: CTRL: Starting call (launching pppd, opening GRE)
Nov 23 16:28:21 zeropage pppd[7280]: Plugin /usr/lib/pptpd/pptpd-logwtmp.so loaded.
Nov 23 16:28:21 zeropage pppd[7280]: pppd 2.4.4 started by root, uid 0
Nov 23 16:28:21 zeropage pppd[7280]: Using interface ppp0
Nov 23 16:28:21 zeropage pppd[7280]: Connect: ppp0 <--> /dev/pts/2
Nov 23 16:28:21 zeropage pptpd[7279]: GRE: Bad checksum from pppd.
Nov 23 16:28:51 zeropage pppd[7280]: LCP: timeout sending Config-Requests
Nov 23 16:28:51 zeropage pppd[7280]: Connection terminated.
Nov 23 16:28:51 zeropage pppd[7280]: Modem hangup
Nov 23 16:28:51 zeropage pppd[7280]: Exit.
Nov 23 16:28:51 zeropage pptpd[7279]: GRE: read(fd=6,buffer=8058660,len=8196) from PTY failed: status = -1 error = Input/output error, usually caused by unexpected termination of pppd, check option syntax and pppd logs
Nov 23 16:28:51 zeropage pptpd[7279]: CTRL: PTY read or GRE write failed (pty,gre)=(6,7)
Nov 23 16:28:51 zeropage pptpd[7279]: CTRL: Reaping child PPP[7280]
Nov 23 16:28:51 zeropage pptpd[7279]: CTRL: Client 203.244.218.56 control connection finished


 어쨋든 그래서 openvpn 을 다시 한번 시도를 해보았지만, 기존에 존재하는 국내 문서중에는 openvpn을 우분투 패키지를 이용해서 설정한 내용이 없어서, 설정을 시도하면서 문서로 남겨볼겸 이렇게 글을 적고 있다.

참고문서) http://www.ventanazul.com/webzine/articles/openvpn-ubuntu-and-hulu

더보기


우선, 패키지 관리자를 이용해서 openvpn 패키지를 설치한다. apt-get, aptitude, synaptic 무엇을 패키지 설치에 이용해도 무방할 것이다. 개인적 기호에 의해서 aptitude 를 이용해서 설치했다.

root@zeropage:~# sudo su
root@zeropage:~# aptitude install openvpn

설치를 한뒤 아래의 명령어로 기본 설정파일 위치를 지정한다.
root@zeropage:/etc/openvpn#vi /etc/default/openvpn
해당 파일을 열고 이전에 존재하는 모든 내용을 comment 처리 한뒤, AUTOSTART="openvpn" 을 마지막에 추가한다.

이렇게 설정해주면 openvpn 은 구동시 /etc/openvpn/openvpn.conf 설정을 찾는데, 현재는 존재하지 않기 때문에 따로 작성을 할 것이다.

다음 작업할 내용은 키와 인증서를 만드는 일이다.
root@zeropage:/etc/openvpn#cd /etc/openvpn/

rsa 설정을 위해서 예제 설정 파일을 복사해온다.
root@zeropage:/etc/openvpn#cp -r /usr/share/doc/openvpn/examples/easy-rsa/ .
root@zeropage:/etc/openvpn#vi easy-rsa/vars
위의 파일이 존재하지 않는 상황이라면 아래의 위치에서 설정 파일을 찾아보자.
root@zeropage:/etc/openvpn#vi easy-rsa/2.0/vars
해당 파일에서 아래의 내용을 반영한다.

export KEY_COUNTRY=PE
export KEY_PROVINCE=LI
export KEY_CITY=Lima
export KEY_ORG="Nombre-OpenVPN"
export KEY_EMAIL="tu-nombre@example.com"

그리고 아래의 명령어를 이용해서 환경 설정을 현재 터미널에 반영한다.
root@zeropage:/etc/openvpn/easy-rsa/2.0# . ./vars
NOTE: If you run ./clean-all, I will be doing a rm -rf on /etc/openvpn/easy-rsa/2.0/keys

private key 를 작성한다.
root@zeropage:/etc/openvpn/easy-rsa/2.0# ./build-ca
Generating a 1024 bit RSA private key
..............++++++
........................................++++++
writing new private key to 'ca.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [PE]:
State or Province Name (full name) [LI]:
Locality Name (eg, city) [Lima]:
Organization Name (eg, company) [Nombre-OpenVPN]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [Nombre-OpenVPN CA]:
Email Address [tu-nombre@example.com]:

서버키를 작성한다. (서버키 작성 마지막에 certification 을 반드시 작성하도록 y를 선택해야한다)
root@zeropage:/etc/openvpn/easy-rsa/2.0# ./build-key-server server
Generating a 1024 bit RSA private key
...++++++
.................++++++
writing new private key to 'server.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [PE]:
State or Province Name (full name) [LI]:
Locality Name (eg, city) [Lima]:
Organization Name (eg, company) [Nombre-OpenVPN]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [server]:
Email Address [tu-nombre@example.com]:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /etc/openvpn/easy-rsa/2.0/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'PE'
stateOrProvinceName   :PRINTABLE:'LI'
localityName          :PRINTABLE:'Lima'
organizationName      :PRINTABLE:'Nombre-OpenVPN'
commonName            :PRINTABLE:'server'
emailAddress          :IA5STRING:'tu-nombre@example.com'
Certificate is to be certified until Nov 21 08:03:49 2018 GMT (3650 days)
Sign the certificate? [y/n]:
CERTIFICATE WILL NOT BE CERTIFIED

클라이언트 키를 작성한다.
root@zeropage:/etc/openvpn/easy-rsa/2.0# ./build-key-server client
Generating a 1024 bit RSA private key
..................++++++
............++++++
writing new private key to 'client.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [PE]:
State or Province Name (full name) [LI]:
Locality Name (eg, city) [Lima]:
Organization Name (eg, company) [Nombre-OpenVPN]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [client]:
Email Address [tu-nombre@example.com]:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /etc/openvpn/easy-rsa/2.0/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'PE'
stateOrProvinceName   :PRINTABLE:'LI'
localityName          :PRINTABLE:'Lima'
organizationName      :PRINTABLE:'Nombre-OpenVPN'
commonName            :PRINTABLE:'client'
emailAddress          :IA5STRING:'tu-nombre@example.com'
Certificate is to be certified until Nov 21 08:06:02 2018 GMT (3650 days)
Sign the certificate? [y/n]:
CERTIFICATE WILL NOT BE CERTIFIED

Diffie Hellman 파라메터를 생성한다.
root@zeropage:/etc/openvpn/easy-rsa/2.0# ./build-dh
root@zeropage:/etc/openvpn/easy-rsa/2.0# ./build-dh
Generating DH parameters, 1024 bit long safe prime, generator 2
This is going to take a long time
.........+....................................+................+.........................................+.............................................................................+...................+.............................................+....+........................+..........................................................................................+...........................................+............................+.............................................................................++*++*++*

이제 기본적인 키 작성 작업이 끝났다. 클라이언트 측에서 서버로의 접속을 위해서는 /etc/openvpn/easy-rsa/keys 디렉토리내에 3개의 파일이 필요하니 잘 보관한다.
ca.crt
client1.crt
client1.key

openvpn 환경 설정 파일을 만들어야한다.

root@zeropage:/etc/openvpn# vi openvpn.conf
dev tun
proto tcp
port 1194
ca /etc/openvpn/easy-rsa/2.0/keys/ca.crt
cert /etc/openvpn/easy-rsa/2.0/keys/server.crt
key /etc/openvpn/easy-rsa/2.0/keys/server.key
dh /etc/openvpn/easy-rsa/2.0/keys/dh1024.pem
user nobody
group nogroup
server 10.8.0.0 255.255.255.0
persist-key
persist-tun
#status openvpn-status.log
#verb 3
client-to-client
push "redirect-gateway def1"
#log-append /var/log/openvpn
comp-lzo

그리고 IP라우팅을 위해서 아래의 커맨드를 한번씩 날려준다.

echo 1 > /proc/sys/net/ipv4/ip_forward
sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
sudo iptables -L -t nat

(차후 방화벽 정책 삭제를 위해서는 sudo iptables -F -t nat)
서버쪽 설정은 완료 되었음을 알 수 있다.

root@zeropage:/etc/openvpn# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:17:31:f3:11:1e 
          inet addr:165.194.17.160  Bcast:165.194.17.255  Mask:255.255.255.0
          inet6 addr: fe80::217:31ff:fef3:111e/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:34354629 errors:0 dropped:0 overruns:0 frame:0
          TX packets:14478158 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:355495487 (339.0 MB)  TX bytes:744316533 (709.8 MB)
          Interrupt:217 Base address:0x8000

eth1      Link encap:Ethernet  HWaddr 00:48:54:4a:e0:c7 
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:20 Base address:0xac00

lo        Link encap:Local Loopback 
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:348697 errors:0 dropped:0 overruns:0 frame:0
          TX packets:348697 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:185131767 (176.5 MB)  TX bytes:185131767 (176.5 MB)

tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 
          inet addr:10.8.0.1  P-t-P:10.8.0.2  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)


자 이제 오늘의 핵심 클라이언트에서 이제 VPN 서버로 한번 붙여보자. ㅋㅋ

VPN서버로 붙일 윈도우에서 http://openvpn.org 에서 제공하는 윈도우용 클라이언트를 받고 설치하자!!!

프로그램 메뉴의 OpenVPN configuration file directory 를 열고 서버에서 생성된 키중 ca.crt, client.crt, client.key 를 복사하고, client.ovpn 파일을 열고 remote 항목을 수정하면 종료!!!
##############################################
# Sample client-side OpenVPN 2.0 config file #
# for connecting to multi-client server.     #
#                                            #
# This configuration can be used by multiple #
# clients, however each client should have   #
# its own cert and key files.                #
#                                            #
# On Windows, you might want to rename this  #
# file so it has a .ovpn extension           #
##############################################
# Specify that we are a client and that we
# will be pulling certain config file directives
# from the server.
client
# Use the same setting as you are using on
# the server.
# On most systems, the VPN will not function
# unless you partially or fully disable
# the firewall for the TUN/TAP interface.
;dev tap
dev tun
# Windows needs the TAP-Win32 adapter name
# from the Network Connections panel
# if you have more than one.  On XP SP2,
# you may need to disable the firewall
# for the TAP adapter.
;dev-node MyTap
# Are we connecting to a TCP or
# UDP server?  Use the same setting as
# on the server.
;proto tcp
proto udp
# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
remote 165.194.17.160 1194
;remote my-server-2 1194
# Choose a random host from the remote
# list for load-balancing.  Otherwise
# try hosts in the order specified.
;remote-random
# Keep trying indefinitely to resolve the
# host name of the OpenVPN server.  Very useful
# on machines which are not permanently connected
# to the internet such as laptops.
resolv-retry infinite
# Most clients don't need to bind to
# a specific local port number.
nobind
# Downgrade privileges after initialization (non-Windows only)
;user nobody
;group nobody
# Try to preserve some state across restarts.
persist-key
persist-tun
# If you are connecting through an
# HTTP proxy to reach the actual OpenVPN
# server, put the proxy server/IP and
# port number here.  See the man page
# if your proxy server requires
# authentication.
;http-proxy-retry # retry on connection failures
;http-proxy [proxy server] [proxy port #]
# Wireless networks often produce a lot
# of duplicate packets.  Set this flag
# to silence duplicate packet warnings.
;mute-replay-warnings
# SSL/TLS parms.
# See the server config file for more
# description.  It's best to use
# a separate .crt/.key file pair
# for each client.  A single ca
# file can be used for all clients.
ca ca.crt
cert client.crt
key client.key
# 위의 3개의 값을 절대경로를 함께 넣어서 "c:\\program files\\openvpn\\config\\key\...." 형태로 지정해야함.
# Verify server certificate by checking
# that the certicate has the nsCertType
# field set to "server".  This is an
# important precaution to protect against
# a potential attack discussed here:
http://openvpn.net/howto.html#mitm
#
# To use this feature, you will need to generate
# your server certificates with the nsCertType
# field set to "server".  The build-key-server
# script in the easy-rsa folder will do this.
;ns-cert-type server
# If a tls-auth key is used on the server
# then every client must also have the key.
;tls-auth ta.key 1
# Select a cryptographic cipher.
# If the cipher option is used on the server
# then you must also specify it here.
;cipher x
# Enable compression on the VPN link.
# Don't enable this unless it is also
# enabled in the server config file.
comp-lzo
# Set log file verbosity.
verb 3
# Silence repeating messages
;mute 20



오케이 이렇게 하고 접속하면 VPN 성공... ㅋㅋㅋ

ps. 근데 또 안붙네... ㅡㅡ;; 덜덜 역시 외부망으로는 못붙는건가... 영 이상한디 ㅜ.ㅜ
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 박영창


더보기


크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 박영창


더보기




크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 박영창

더보기


크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 박영창

도메인 신청에 대해서 아무것도 모르던 때에 현재 도메인을 구입해서 상대적으로 가격이 엄청 비쌌던 후이즈에서 신청을 했었습니다. (후이즈는 왜 이렇게 비쌀까요?)

전 원래 그 가격에만 등록이 돼는 줄 알았는데... 쩝...

하여간 슬슬 기간도 반년정도만 남아서 dotname으로 등록 기관을 이전했습니다.

생각보다 엄청 간단하더군요. ;;

그냥 기존의 등록기관에서 AUTH CODE를 받아서 새로운 등록 기관으로 신청만 하면 돼더라는...

사용자 삽입 이미지

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 박영창
멤에서 이번에 소규모 1주일 텀프로젝트를 시작하면서 절대로 이유없이 프로그램 만들지 않는 내가 ACE를 공부해자는 마음으로 이 놈을 공부를 했다.

단순히 통신을 이루는 행위 자체는 굉장히 간단했다.

ACE 프레임워크 스택



문제는 이런 것이 아니라... 도대체 내가 만드는 코드가 밑에서 어떻게 돌아가는지 알 수가 없었다. MFC 도 아닌 녀석이 MFC 흉내를 내는 건지;;;

확실히 소켓처럼 저순으로 돌아가는 내용을 몰라도 프로그램을 잘 작성된다. 하지만 그것뿐이다. 절대로 처음 네트워크를 프로그래밍하는 사람에게는 비추인 녀석이다. 덴장;;;

프레임웍은 DP를 공부하는 목적으로 대단히 적합하다. 그만큼 방대하기 이를데 없고.... 이런것까지 ACE에서 지원해야하나 싶을 정도로 엄청나다.
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 박영창
Distance Vector Routing Protocol
A distance-vector routing protocol is a routing protocol used in routing of packet-switched networks in computer communications, as in for example the Routing Information Protocol for Internet traffic. They use the Bellman-Ford algorithm to calculate paths.

Examples of distance-vector routing protocols include RIPv1 or 2 and IGRP.

Working
The distance-vector routing protocol assumes a network connected through several
routers, each of which is connected to two or more computer networks. Each network may be connected to one or more routers.

The description below describes a very simple distance-vector routing protocol:

  1. In the first stages, the router makes a list of which networks it can reach, and the cost to reach them (cost is protocol dependent, in RIP case, the cost is measured by number hops). In the outset this will be the two or more networks to which this router is connected. The number of hops for these networks will be 1. This table is called a routing table.
  2. Periodically (typically every 30 seconds) the routing table is shared with other routers on each of the connected networks via some specified inter-router protocol. These routers will add 1 to every hop-count in the table, as it associates a hop cost of 1 for reaching the router that sent the table. This information is just shared inbetween physically connected routers ("neighbors"), so routers on other networks are not reached by the new routing tables yet.
  3. A new routing table is constructed based on the directly configured network interfaces, as before, with the addition of the new information received from other routers. The hop-count is used as a cost measure for each path. The table also contains a column stating which router offered this hop count, so that the router knows who is next in line for reaching a certain network.
  4. Bad routing paths are then purged from the new routing table. If two identical paths to the same network exist, only the one with the smallest hop-count is kept. When the new table has been cleaned up, it may be used to replace the existing routing table used for packet forwarding.
  5. The new routing table is then communicated to all neighbors of this router. This way the routing information will spread and eventually all routers know the routing path to each network, which router it shall use to reach this network, and to which router it shall route next.

Advantage and Disadvantage
Distance-vector routing protocols are simple and efficient in small networks, and require little, if any management. However, they do not
scale well, and have poor convergence properties, which has led to the development of more complex but more scalable link-state routing protocols for use in large networks. They suffer from the "Count to Infinity problem".


Link State Routing Protocol
A link-state routing protocol is one of the two main classes of routing protocols used in packet-switched networks for computer communications. Examples of link-state routing protocols include OSPF and IS-IS.

The link-state protocol is performed by every switching node in the network (i.e. nodes which are prepared to forward packets; in the Internet, these are called routers). The basic concept of link-state routing is that every node receives a map of the connectivity of the network, in the form of a graph showing which nodes are connected to which other nodes.

Each node then independently calculates the best next hop from it for every possible destination in the network. (It does this using only its local copy of the map, and without communicating in any other way with any other node.) The collection of best next hops forms the routing table for the node.

This contrasts with distance-vector routing protocols, which work by having each node share its routing table with its neighbors. In a link-state protocol, the only information passed between the nodes is information used to construct the connectivity maps.

Detailed Description : Distributing maps
This description covers only the simplest configuration; i.e. one with no areas, so that all nodes do have a map of the entire network. The hierarchical case is somewhat more complex; see the various protocol specifications.

As previously mentioned, the first main stage in the link-state algorithm is to give a map of the network to every node. This is done with several simple subsidiary steps.

Determining the neighbours of each node
First, each node needs to determine what other nodes it is connected to, over fully-working links; it does this using a simple reachability protocol which it runs separately with each of its directly-connected neighbours.

Distributing the information for the map
Next, each node periodically makes up a short message, the link-state advertisement, which:

Identifies the node which is producing it.
Identifies all the other nodes to which it is directly connected.
Includes a sequence number, which increases every time the source node makes up a new version of the message.
This message is then flooded throughout the network. As a necessary precursor, each node in the network remembers, for every other node in the network, the sequence number of the last link-state message which it received from that node. With that in hand, the method used is simple.

Starting with the node which originally produced the message, it sends a copy to all of its neighbours. When a link-state advertisement is received at a node, the node looks up the sequence number it has stored for the source of that link-state message. If this message is newer (i.e. has a higher sequence number), it is saved, and a copy is sent in turn to each of that node's neighbours.

This procedure rapidly gets a copy of the latest version of each node's link-state advertisement to every node in the network.

Creating the map
Finally, with the complete set of link-state advertisements (one from each node in the network) in hand, it is obviously easy to produce the graph for the map of the network.

The algorithm simply iterates over the collection of link-state advertisements; for each one, it makes links on the map of the network, from the node which sent that message, to all the nodes which that message indicates are neighbours of the sending node.

No link is considered to have been correctly reported unless the two ends agree; i.e. if one node reports that it is connected to another, but the other node does not report that it is connected to the first, there is a problem, and the link is not included on the map.

Notes about this stage
The link-state message giving information about the neighbours is recomputed, and then flooded throughout the network, whenever there is a change in the connectivity between the node and its neighbours, e.g. when a link fails. Any such change will be detected by the reachability protocol which each node runs with its neighbours.

Detailed description: Calculating the routing table
As initially mentioned, the second main stage in the link-state algorithm is to produce routing tables, by inspecting the maps. This is again done with several steps.

Calculating the shortest paths
Each node independently runs an algorithm over the map to determine the shortest path from themselves to every other node in the network; generally some variant of Dijkstra's algorithm is used.

Basically, a node maintains two data structures: a tree containing nodes which are "done", and a list of candidates. The algorithm starts with both structures empty; it then adds to the first one the node itself. The algorithm then repetitively:

Adds to the second (candidate) list all nodes which are connected to the node just added to the tree (excepting of course any nodes which are already in either the tree or the candidate list).
Of the nodes in the candidate list, moves to the tree (attaching it to the appropriate neighbour node already there) the one which is the closest to any of the nodes already in the tree.
Repeat as long as there are any nodes left in the candidate list. (When there are none, all the nodes in the network will have been added to the tree.)
This procedure ends with the tree containing all the nodes in the network, with the node on which the algorithm is running as the root of the tree. The shortest path from that node to any other node is indicated by the list of nodes one traverses to get from the root of the tree, to the desired node in the tree.

Filling the routing table
With the shortest paths in hand, filling in the routing table is again obviously easy.

For any given destination node, the best next hop for that destination is the node which is the first step from the root node, down the branch in the shortest-path tree which leads toward the desired destination node.

To create the routing table, it is only necessary to walk the tree, remembering the identity of the node at the head of each branch, and filling in the routing table entry for each node one comes across with that identity.

Optimizations to the algorithm
The algorithm described above was made as simple as possible, to aid in ease of understanding. In practise, there are a number of optimizations which are used.

Most importantly, whenever a change in the connectivity map happens, it is necessary to recompute the shortest-path tree, and then recreate the routing table. The BBN work discovered how to recompute only that part of the tree which could have been affected by a given change in the map.

Also, the routing table would normally be filled in as the shortest-path tree is computed, instead of making it a separate operation.

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 박영창

Adhoc Network

In computer networking, ad-hoc is a network connection method which is most often associated with wireless devices. The connection is established for the duration of one session and requires no base station. Instead, devices discover others within range to form a network for those computers. Devices may search for target nodes that are out of range by flooding the network with broadcasts that are forwarded by each node. Connections are possible over multiple nodes (multihop ad-hoc network). Routing protocols then provide stable connections even if nodes are moving around. Both Nintendo's DS and Sony's PlayStation Portable use Ad-Hoc connections for wireless multiplayer gaming.

See IEEE 802.11, Bluetooth, or ultra-wide band. The alternative is infrastructure, with a base station that manages the network for its range.

The term ad-hoc network can also refer to an independent basic service set (IBSS).


Sensor network

A sensor network is a computer network of many, spatially distributed devices using sensors to monitor conditions at different locations, such as temperature, sound, vibration, pressure, motion or pollutants. Usually these devices are small and inexpensive, so that they can be produced and deployed in large numbers, and so their resources in terms of energy, memory, computational speed and bandwidth are severely constrained. Each device is equipped with a radio transceiver, a small microcontroller, and an energy source, usually a battery. The devices use each other to transport data to a monitoring computer.

Sensor networks involve three areas: sensing, communications, and computation (hardware, software, algorithms). Very useful technologies are wireless database technology such as queries, used in a wireless sensor network, and network technology to communicate with other sensors, especially multihop routing protocols. For example, ZigBee is a wireless protocol used by Motorola in home control systems.

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 박영창

요즘 준비중인 프로그램이 있습니다. 이녀석이 약간은 분산처리와 비슷한 냄새를 풍기는 놈인데... 이녀석을 다루면서 요즘 참 네트워크를 잘 짜기도 힘들겠구나 싶습니다.

제가 말하는 녀석은 C/S모델이 아닌 말그대로 분산형 처리. Self Routing, Self Recovery 모델을 지원하는 네트워크를 구성하는 녀석들을 말합니다. 이 녀석들을 보면 이 프로로콜을 고안하고 구현한 사람들이 결코 평범한 두뇌를 자랑하는 사람이 아니라는 생각이 듭니다. 각자가 C/S 모두인 이 녀석들은 조금만 컨트롤을 잘못해도 네트웍 전체가 엉켜버리는 군요.

아 답답해... ㅡ.ㅡ;; 그래도 결국엔 네트워크를 붙이는 일을 성공했습니다. 이제 제가 구현하려고 한 프로그램의 대충 50% 정도가 완성된 것 같습니다. 아직도 멀었네요. 한 한달은 빡시게 굴러야 완성되지 않을까 싶습니다. ㅜ.ㅜ

크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 박영창
파일 공유 프로토콜인 Gnutella 에 대한 분석글
----
= Gnutella-More Free =

== 시작에 앞서서 ==
늦게 이 글을 올린 것에 대해 미안하다.
이 문서는 내가 아르바이트를 하면서 번역과 작성한 문서이다.
지금의 스펙에서는 라우팅 부분의 맴과 캐쉬와 쉐어에서 많은 부분 수정이 가해졌다.
대부분의 P2P 프로그램들이 누텔라의 방법을 기본으로 작성 되었으며 지금의 유동적
IP를 갖는 환경에서는 이를 뛰어 넘는 방법은 없을 것으로 보여진다.
후에 IPv6가 나온다면 각각의 시스템이 아닌 어플리케이션에 IP를 붙일 수 있게 되어진다고
읽은 적이 있다. 이 때 되면 보다 획기적인 P2P 프로그램이 나올 것으로 보인다.

아래의 글은 가볍게 읽어 주시길....

== 주인장이 생각하는 가장 이상적인 P2P란 ==
그누텔라는 확실히 매력적이고 또한 이상적인 순수 P2P라는 생각이 든다. 하지만 P2P란 많은 부분
희생(?)이 필요하다. 여기서 희생이란 불필요하지만 쓸 수 밖이 없는 대역폭을 말한다.
내가 찾고자 하는 파일이 누가 가지고 있는 지 알고 있다면 굳이 P2P는 필요하지 않을 것이다.

하지만 이러한 희생을 줄이는 것이 보다 좋을 것이라는 생각이 든다. 그런 점에서 내가 생각하는 가장
이상적인 P2P는 e-Donkey라고 생각 되어진다. 물론 지금의 e-Donkey는 아니다. 내가 생각하는 부분으로
고쳐져야 겠지. 하지만 지금의 e-Donkey처럼 개인이 서버를 가질 수 있고 또한 이 서버를 가지고 찾는
다면 불필요한 대역폭은 줄어들 것이고 분산된 서버를 하나의 순수 P2P로 묶고 서버에서 클라이언트의
노드들을 수정해 준다면 가장 이상적이지 않을까? 라고 한 때 무신히 고민했다. 잡소리 이제 그만!!!!

== The Gnutella Protocol Document ==

The Gnutella Protocol Document

1. Protocol Specification

1.1 Gnutella란 Peer to Peer 의 분산 모델로서 Mesh구조의 네트워크망을 가지며
Query전송을 통해 네트워크내 파일의 검색과 다운로드를 가능하게 한다.

1.2 프로토콜 정의
5개의 Descriptor를 사용하고 TCP/IP 프로토콜과 ASCII Code를 기반으로
이용하여 통신이 이루어진다.
- 네트워크망 초기 진입 -
{{{~cpp Connection String : GNUTELLA CONNECTION//nn}}}
{{{~cpp Response Connection : GNUTELLA OKnn}}}
- Note
Note 1 : 모든 데이터 필드는 특별한 말이 없으면 리틀 엔디언
Note 2 : IP 주소는 IPv4 형식으로 쓰인다.
Note 3 : Protocol은 Header와 Payload로 구성
- 헤더
Descriptor ID (16 byte): 네트워크 상의 고유 식별자
Payload Descriptor (2 byte): 명령어의 식별자
TTL (1 byte): 네트워크의 Servent를 지날 때마다 감소하는 수 /
네트워크 부하를 줄이기 위해 쓰임
Hops (1 byte): 지나간 Servent수
Payload Length (4 byte): Header 다음에 따라오는 Descriptor 의 길이
Data가 스트림이기 때문에 공백이나 Pad Byte가 따라오지않는다.
Gnutella 프로토콜의 경우 synch를 맞추는 특별한 byte가 존재하지 않아
형식에 틀린 Descriptor는 폐기된다.

|| DescriptorID || Payload Descriptor || TTL || hops || PayloadLength ||
0 15 16 17 18 19 22

- 디스크립터 (Descriptor)
표1)
|| 색인 || 설명 ||
|| ping || 네트워크상의 호스트를 찾을 때 쓰인다. Payload가 없기 때문에 header의 Payload_Length = 0x00000000 로 설정된다. ||
|| pong || Ping을 받으면 주소와 기타 정보를 포함해 응답한다.Port / IP_Address / Num Of Files Shared / Num of KB Shared** IP_Address - Big endian ||
|| query ||네트워크상에서 검색에 쓰이고 검색 Minimum Speed ( 응답의 최소 속도 ), Search Criteria 검색 조건 ||
|| queryHit || 검색 Query 조건과 일치한 경우 QueryHit로 응답한다. Num Of Hits 조건에 일치하는 Query의 결과 수 Port / IP_Address (Big-endian) / Speed / Result Set File Index ( 파일 번호 ) File Size ( 파일 크기 )File Name ( 파일 이 / 더블 널로 끝남 ) Servent Identifier 응답하는 Servent의 고유 식별자 Push 에 쓰인다. ||
|| push || 방화벽이 설치된 Servent와의 통신을 위한 DescriptorServent Identifier / File Index / IP_Address(Big-endian)/Port||

1.3 명령어 라우팅
1. Pong 은 Ping이 왔던 같은 길을 따라 전송된다. 만약 DescriptorID가 n
인 Pong을 받았는 데 Descriptor ID가 n인 Ping 보지 못했다면 Ping을 보
낸 Servent는 네트워크 상에서 제거된 것을 의미한다.
2. QueryHit와 Query -
3. Push/QueryHit -
4. 전달 되었던 Ping과 Query를 제외하고 모든 Ping과 Query는 연결 된
모든 Servent에 전송된다.
5. TTL/Hop은 다른 Servent로 전송되기 전에 변경되며 후에 TTL이
0이면 다른 Servent로 전송되지 않는다.
6. 전에 전송된 Descriptor는 다시 전송되지 않는다. 네트워크 부하 줄임

1.4 파일 다운로드
QueryHit 명령어를 받으면 파일을 초기화 하고 다운로드를 시작한다.
이는 Gnutella 네트워크를 이용하는 것이 아니라 기존의 HTTP 프로토콜
을 이용하여 직접 파일이 전송된다.
GET/get///HTTP/1.0rn
Connection:Keep-Alivern
Range:bytes=0-rn
User-Agent:Gnutellarn3
rn
Range가 파일의 이어받기가 가능하게 함.
는 파일 번호이고 이는 QueryHit Result에 포함된 내용이다.
이와같은 HTTP 헤더를 받으면 서버는 다음과 같은 헤더를 보내준다.
HTTP 200 OKrn
Server:Gnutellarn
Content-type:application/binaryrn
Content-length:435678rn
rn
바로 다음에 데이터가 Content-length만큼 따라오게 된다.

1.5 방화벽이 설치된 Servents
방화벽으로 인해 직접 연결이 불가능한 경우 Push Descriptor를 보내고 라우팅을 통해 받은
QueryHit에 대한 응답으로 새로운 TCP/IP 연결이 생긴
다.
새롭게 연결 된 후
GIV:/nn 를 보내 파일
을 요청하면
GET/get///HTTP1.0rn
Connection:Keep-Alivern
Range:bytes=0-rn
User-Agent:Gnutellarn3
rn
과 같은 HTTP GET request형식으로 응답을 하며 파일을 전송한다.
그러나 Push Descriptor조차 보내지 못하면 파일전송은 불가능하다.

1.6 확장된 Gnutella 프로토콜
기존의 Gnutella가 다른 프로그램(BearShare) 에 의해 서비스 되면서
확장된 프로토콜 이 필요하게 되었다. 이를 Triler라고 하며 QueryHit 의
ResultSet 마지막 더블널 과 Servent ID사이에 들어간다.
- Trailer
VendorCode(3byte) OpenDataSize(1byte) OpenData(2byte) PrivateData(n)

2. Gnutella Core Code
2.1 Data Structure
File Name : Packet.Cpp
Common IP / ExIP / Node / NodeEx
GnutellaPacket packet_Header / packet_Ping / packet_Pong
packet_Push / packet_Query / packet_QueryHit

2.2 Class Hierarchal Diagram

3. Gnucleus Technical Description
Gnuclues는 Gnutella 프로젝트 중 OpenSoure로 실제 인터페이스 부분이 열악하다.
하지만 Gnucleus의 Core 코드 부분의 Docunment가 가장 잘 나와있고 실제로
Compile / Execute 가능한 Code를 손에 얻을 수 있는 프로그램이다. 물론
지금 상태는 버전의 호환성으로 인해 Gnucleus node에 실제 노드에 접속하는 것이
어렵지만 같은 버전 사이의 접속은 가능하므로 인터페이스 부분을 수정한다면
보다 좋은 프로그램으로 변형할 수 있을 것 같다.
또한 Entica에서 필요로하는 Search / MultiThreadDownloader를 지원하며
또한 가장 기본적인 기능을 구현하여 불필요한 소스코드가 적다는 장점도 있다.
이런 이유로 다른 몇몇 Gnutella 프로그램도 Gnucleus를 기반으로 작성 되어졌다.

4. Note
servent : server 와 client 의 합성어
little endian byte : 작은 쪽 (바이트 열에서 가장 작은 값)이 먼저 저장되는 순서
descriptor : 패킷이 갖는 의미
payload : 패킷 갖는 데이타

5. 참고 URL

http://www.gnucleus.com/ (Gnucleus 프로그램)

http://www.sourceforge.net/ (Gnutella Clone 프로그램)

http://www.gnutelladev.com/source/gnucleus0.html (소스코드)

CVS// http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/gnucleus/(최근의 소스코드)


== 기타 코드에 관한 설명 ==
----

Gnucleus에서 다운로드 받는 방법에 대한 설명
{{{~cpp
void CSearchResults::OnButtonDownload()
{
std::list::iterator itGroup;
POSITION pos = m_lstResults.GetFirstSelectedItemPosition();

while(pos)
{
int nItem = m_lstResults.GetNextSelectedItem(pos);
ResultGroup* pGroup = (ResultGroup*) m_lstResults.GetItem(nItem);

if(pGroup)
RelayDownload(*pGroup);
}
}
}}}
에서 다운로드 버튼을 누르면 결과 그룹중에서 pos를 기억하고 이 pos를 이용해 다운받을
파일을 선택하고 그 그룹의 결과값을 RelayDownload 함수의 전달인자로 보낸다.
{{{~cpp
void CSearchResults::RelayDownload(ResultGroup &Item) 에서는
CGnuDownloadShell* Download = new CGnuDownloadShell(m_pComm);
}}}
에서와 같이 새로운 다운로드 쉘을 만들고
{{{~cpp
m_pComm->m_DownloadList.push_back(Download);
}}}
와 같이 m_DownloadList에 Download 객체를 삽입하고 CGnuControl에서 제어하게 만든다.
{{{~cpp
Download->m_Name = Item.Name;
Download->m_Search = ReSearch;
Download->m_FileLength = Item.Size;
Download->m_AvgSpeed = Item.AvgSpeed;
}}}
같이 초기화를 한다.
{{{~cpp
// Add hosts to the download list
for(int i = 0; i < Item.ResultList.size(); i++)
Download->AddHost( Item.ResultList[i] );
}}}
처럼 DownloadShell에 AddHost함수를 통해 Item의 모든 Host를 다운로드 에 넣는다.
그러면 View 에 Download에 관한 페이지를 업데이트하고 DownloadShell의 생성자가 실행이 된다.


CGnuControl에서의 void CGnuControl::ManageDownloads()에 의해 제어된다.
void CGnuDownloadShell::Start() 로 다운로드가 시작이 되고 실제적인 다운로드는 CGnuDownload에서 이루어지면 쉘에서는 Timer()에서 CheckCompletion()로 완료 되었는 지 확인을 하게 되고 AttachChunk2Chunk 와 AttachChunk2Partial로 부분부분 완료된 Chunk들을 결합해 주는 역활을 하게 된다.
실제적으로 하나의 Host마다 CGnuDownload 클래스를 갖게 되며 데이타를 받는 소켓이 된다m_StartPos가 받기 시작하는 Chunk의 시작을 나타내며 ReadyFile()에서는 전의 받던 파일이 있는 지 조사후에 File을 연다.
StartDownload() 함수에서 다운로드를 시작하며 GetStartPos() 를 통해 Chunk가 다운로드가 시작할 m_pChunk->m_StartPos의 위치를 알게 한다.
{{{~cpp
m_StartPos = m_pShell->m_BytesCompleted + ((m_pShell->m_FileLength - m_pShell->m_BytesCompleted) / 2);
m_pChunk->StartPos = m_StartPos;
m_pChunk->FileLength = m_pShell->m_FileLength - m_StartPos;
}}}
공식으로 Chunk의 시작위치를 구한다.
SendRequest() 에서 HTTP/GET 형식으로 헤더를 보내 받고자 하는 데이타를 요청한다
OnReceive(int nErrorCode) 에서 Content-length 만큼의 버퍼 데이타를 받아 청크와 연결 시킨다.
이어 받기를 할때에는 파일의 끝에서 -4096만큼 얻고 m_Verification 블럭의 4096크기 만큼 비교를 한 후에 이어받기를 시작한다.
새로운 청크를 만드는 조건은 이미 완료된 청크의 남은 부분이 EmptySize > 16384 보다 커야
한다는 것이다.
소스는 다음과 같고
{{{~cpp
// Reset m_pChunk because this can be called multiple times
if(m_pChunk)
{
bool destroy = true;
for(int i = 0; i < m_pShell->m_ChunkList.size(); i++)
if(m_pShell->m_ChunkList[i] == m_pChunk)
destroy = false;

if(destroy)
delete m_pChunk;

m_pChunk = NULL;
}
}}}
부분은 소켓의 청크중에 지금의 청크가 없다면 지금 받은 청크는 끝마친 것으로
생각하고 m_pChunk = NULL로 만든다




----

Gnucleus에서 프로토콜 통신

GnuCreateGuid(&Guid) // DescriptorID 생성
라우팅시 연결된 모든 nodeList에서 key->Origin를 찾아내어 key->Origin를 제외한 모든 node에 받은 pong 또는 queryHit를 전달
- Search
{{{~cpp
int length = 25 + m_Search.GetLength() + 1;
pNode->SendPacket(m_Packet, length, PACKET_QUERY, true);
}}}
- Result Set
{{{~cpp
// Extract results from the packet
while(HitsLeft > 0 && NextPos < Length - 16)
{
Result Item;

memcpy(&TempX, &Packet[NextPos], 4);
Item.FileIndex = makeD( flipX(TempX));
memcpy(&TempX, &Packet[NextPos + 4], 4);
Item.Size = makeD( flipX(TempX));

Item.Host = QueryHit->Host;
Item.Port = QueryHit->Port;
Item.Speed = makeD( flipX(QueryHit->Speed));

Item.Firewall = Firewall;
Item.Busy = Busy;
Item.Stable = Stable;
Item.ActualSpeed = ActualSpeed;

if(ExtendedPacket)
Item.Vendor = Vendor;

Item.Origin = Log->Origin;
memcpy(&Item.PushID, &Packet[Length - 16], 16);
Item.Distance = Log->Header->Hops;

// Get Filename
for(i = NextPos + 8; Packet[i] != 0; i++)
if(i < Length - 16)
Item.Name += (char) Packet[i];
else
break;

// Pass any data between double null
while(Packet[++i] != 0)
if(i > Length - 16)
break;


Item.NameLower = Item.Name;
Item.NameLower.MakeLower();
Item.Icon = m_pDoc->GetIconIndex(Item.NameLower);

m_WholeList.push_back(Item);

// Screen Item to user's preferences
if(Inspect(Item))
{
m_CurrentList.push_back(Item);
m_tabResults->UpdateList( AddtoGroup(Item) );
}

// Check for end of reply packet
if(i + 1>= Length - 16)
HitsLeft = 0;
else
{
HitsLeft--;
NextPos = i + 1;
}
}

}}}
패킷의 packet_QueryHit 에서 ResultSet을 추출하여 Item Vector에 넣어준다.
{{{~cpp
void CGnuNode::Recieve_Ping(packet_Ping* Ping, int nLength)
key_Value* key = m_pComm->m_TableRouting.FindValue(&Ping->Header.Guid);
}}}
통해 받았던 핑인지 검사하고 if(key == NULL) 받았던 핑이 아니라 새로운 핑이라면 m_pComm->m_TableRouting.Insert(&Ping->Header.Guid, this) 처럼 라우팅 테이블에 넣고 Pong을 보내준다.

----

방화벽이 설치된 경우의 자세한 설명
{{{~cpp
UINT AttemptPort = pPrefs->m_ForcedPort ? pPrefs->m_ForcedPort : pPrefs->m_LocalPort;
AttemptPort += rand() % 99 + 0;
}}}
Firewall에 있을 경우 이런 방법으로 포트를 열지 못하면 랜덤한 포트를 부여 ForcedPort로 접속 Attempts < 3 만큼 시도를 한다.
그리고 PUSH를 Route PUSH를 통해 보내 그누텔라 default 포트가 아닌 열 수 있는 포트로 직접연결을 한다.
만약 상대방 서버가 FireWall에 있다면 QueryHit중의 bool Firewall;필드가 True가 되므로 이에 대한 응답으로
{{{~cpp
Item.Host = QueryHit->Host; Item.Port = QueryHit->Port;
}}}
에 해당하는 Port로 Download를 한다.

----

== Thread ==
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 박영창

최근에 달린 댓글

최근에 받은 트랙백

글 보관함