PHP 네트워크 프로그래밍 샘플

Computer/Web Programming 2010. 4. 1. 17:26
뭔가를 좀 하다가 특정 서버에 TCP 패킷을 보낼 일이 있었다.
컴파일러도 없는 환경에서 C로 짜기는 영 어쩐지 싫고, 깔려있던 PHP로 어찌저찌 해보자는 맘을 가지고 PHP 네트워크 프로그래밍을 좀 찾다가 찾은 참조 소스랑..
짰던 소스랑.

1. 샘플
<?php
error_reporting(E_ALL);
echo "
TCP/IP Connection
\n";
/* Get the port for the WWW service. */
$service_port = getservbyname('www', 'tcp');
/* Get the IP address for the target host. */
$address = gethostbyname('www.example.com');
/* Create a TCP/IP socket. */
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket < 0) {
   echo "socket_create() failed: reason: " . socket_strerror($socket) . "\n";
} else {
   echo "OK.\n";
}
echo "Attempting to connect to '$address' on port '$service_port'...";
$result = socket_connect($socket, $address, $service_port);
if ($result < 0) {
   echo "socket_connect() failed.\nReason: ($result) " . socket_strerror($result) . "\n";
} else {
   echo "OK.\n";
}
$in = "HEAD / HTTP/1.1\r\n";
$in .= "Host: www.daum.net\r\n";
$in .= "Connection: Close\r\n\r\n";
$out = '';
echo "Sending HTTP HEAD request...";
socket_write($socket, $in, strlen($in));
echo "OK.\n";
echo "Reading response:\n\n";
while ($out = socket_read($socket, 2048)) {
   echo $out;
}
echo "Closing socket...";
socket_close($socket);
echo "OK.\n\n";
?>





2. 뭔가 짜다만 소스
<?php
$Host = "xxx.xxx.xxx.xx";
$Port = "10020";
/* Create a TCP/IP socket. */
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket < 0) {
   echo "socket_create() failed: reason: " . socket_strerror($socket) . "\n";
} else {
   echo "Olleh~! Connected.\n";
}
echo "Attempting to connect to '$Host' on port '$Port'...";
$result = socket_connect($socket, $Host, $Port);
if ($result < 0) {
   echo "socket_connect() failed.\nReason: ($result) " . socket_strerror($result) . "\n";
} else {
   echo "OK.\n";
}
/*
$socket2 = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket2 < 0) {
   echo "socket_create() failed: reason: " . socket_strerror($socket) . "\n";
} else {
   echo "Olleh~! Connected.\n";
}
echo "Attempting to connect to '$Host' on port '$Port'...";
$result = socket_connect($socket2, $ImanHost, 1053);
if ($result < 0) {
   echo "socket_connect() failed.\nReason: ($result) " . socket_strerror($result) . "\n";
} else {
   echo "OK.\n";
}
*/
$in=chr(1)."10".chr(242).chr(0).chr(0).chr(0).chr(135).chr(0).chr(0).chr(0)."I&bodytype=0&from=IMAN04/10dd3/0/imanBuddyService&svc=profilesvr&to=I08".chr(0).chr(0).chr(0)."6&cmd=profile&kid=3H00107555@company.co.kr&lparam=&version=1";
$out = '';
echo "Sending TCP request...";
if (socket_write($socket, $in, strlen($in)) <0 ) echo "Error.\n";
else echo "OK.\n\n";
echo "Reading response:\n\n";
while ($out = socket_read($socket, 4096)) {
   echo $out;
}
echo "Closing socket...";
socket_close($socket);
echo "OK.\n\n";
 
/*
Original Packet
00000000  01 31 30 F2 00 00 00 87  00 00 00 49 26 62 6F 64   .10..... ...I&bod
00000010  79 74 79 70 65 3D 30 26  66 72 6F 6D 3D 49 4D 41   ytype=0& from=IMA
00000020  4E 30 38 2F 31 30 37 39  64 2F 30 2F 69 6D 61 6E   N08/1079 d/0/iman
00000030  42 75 64 64 79 53 65 72  76 69 63 65 26 73 76 63   BuddySer vice&svc
00000040  3D 70 72 6F 66 69 6C 65  73 76 72 26 74 6F 3D 49   =profile svr&to=I
00000050  4D 41 4E 30 38 00 00 00  36 26 63 6D 64 3D 70 72   MAN08... 6&cmd=pr
00000060  6F 66 69 6C 65 26 6B 69  64 3D 33 48 30 30 31 30   ofile&ki d=3H0010
00000070  37 35 35 35 40 6B 74 2E  63 6F 2E 6B 72 26 6C 70   7555@company. co.kr&lp
00000080  61 72 61 6D 3D 26 76 65  72 73 69 6F 6E 3D 31      aram=&ve rsion=1

내가 보낸 아이들.
00000000  01 31 30 F2 00 00 00 87  00 00 00 49 26 62 6F 64   .10..... ...I&bod
00000010  79 74 79 70 65 3D 30 26  66 72 6F 6D 3D 49 4D 41   ytype=0& from=IMA
00000020  4E 30 38 2F 31 30 37 39  64 2F 30 2F 69 6D 61 6E   N08/1079 d/0/iman
00000030  42 75 64 64 79 53 65 72  76 69 63 65 26 73 76 63   BuddySer vice&svc
00000040  3D 70 72 6F 66 69 6C 65  73 76 72 26 74 6F 3D 49   =profile svr&to=I
00000050  4D 41 4E 30 38 2E 2E 2E  36 26 63 6D 64 3D 70 72   MAN08... 6&cmd=pr
00000060  6F 66 69 6C 65 26 6B 69  64 3D 33 48 30 30 31 30   ofile&ki d=3H0010
00000070  37 35 35 35 40 6B 74 2E  63 6F 2E 6B 72 26 6C 70   7555@company. co.kr&lp
00000080  61 72 61 6D 3D 26 76 65  72 73 69 6F 6E 3D 31      aram=&ve rsion=1

.10........I&bodytype=0&from=IMAN08/1079d/0/imanBuddyService&svc=profilesvr&to=IMAN08...6&cmd=profile&kid=3H00107555@company.co.kr&lparam=&version=1
01:31:30:F2:00:00:00:87:00:00:00:49:26:62:6F:64:79:74:79:70:65:3D:30:26:66:72:6F:6D:3D:49:4D:41:4E:30:38:2F:31:30:37:39:64:2F:30:2F:69:6D:61:6E:42:75:64:64:79:53:65:72:76:69:63:65:26:73:76:63:3D:70:72:6F:66:69:6C:65:73:76:72:26:74:6F:3D:49:4D:41:4E:30:38:00:00:00:36:26:63:6D:64:3D:70:72:6F:66:69:6C:65:26:6B:69:64:3D:33:48:30:30:31:30:37:35:35:35:40:6B:74:2E:63:6F:2E:6B:72:26:6C:70:61:72:61:6D:3D:26:76:65:72:73:69:6F:6E:3D:31
?10????????I&bodytype=0&from=IMAN08/1079d/0/imanBuddyService&svc=profilesvr&to=IMAN08???6&cmd=profile&kid=3H00107555@company.co.kr&lparam=&version=1
*/
 
?>

보안상 문제될(?) 부분을 약간씩 고치다보니 저대로 돌리면 당근 안돌아간다.
아무튼 잘 짜놓고서 콘솔에서 php xxx.php 하면 이쁘게 돌아간다.

요약하면..
1. PHP로 간단히 TCP 패킷 송수신 프로그램을 짤 수 있다는 것
2. 패킷 캡쳐링 했던 것과 텍스트로 같은 패킷을 보낼때는 캡쳐상의 . 이나 기타 공백 등 특수 아스키 코드가 눈에 보이는 것과 값이 다를 수 있다. 그래서 만들어서 송신하는 패킷도 테스트하여 잡아보고, 헥사코드로 다른 점이 발견되면 아래와 같이 string에 아스키 코드 실제값으로 이어붙여줄 필요가 있다.
$in=chr(1)."10".chr(242).chr(0).chr(0).chr(0).chr(135).chr(0).chr(0)...
3. PHP 프로그래밍은 쉽다 + 그래도 이건 너무 대충대충 짰다. ;

PC 1대에서 복수 네트워크 동시에 사용하기

Computer/ETC 2009. 3. 27. 01:00

사실 어찌저찌 하다보면 아래와 같은 상황은 자주 발생한다.
차단된 Network를 우회하기 위해, 아니면 메인 네트워크의 throughput 등에 영향을 주지 않고 특정 네트워크에 대한 테스트를 한다거나....등등등.
향후 3G network, WiBro, 기타 WIFI 등 가능한 모든 interface에 대해 아래와 같이 G/W 변경으로 사용 가능하다.

윈도우에서 복수의 네트워크를 연결하고 나면 default gateway가 변경되어 연결 상태가 원하지 않는 우선순위를 갖게 되는 경우가 있다.
예를 들어,
1. 나는 (사내망) 유선을 메인으로, 무선을 특정 프로그램용으로 사용하고 싶은 경우
2. 유선을 잡은 상태에서 무선을 연결하고 나니,
3. default gateway가 무선의 것으로 바뀌어 사내망 접속이 안된다거나 하는 등의.

이런 경우에는 아래 포스트를 참고하여 default gateway를 변경해준다.
http://geniuskch.tistory.com/entry/Windows에서-default-gateway-값-변경

================================================================================
노트북 PC 에서 유선 랜과 무선 랜을 동시에 사용하게 되면,
(라우팅이나 환경에 따라 다르겠지만) 통상 유선을 이용해서 네트워크를 사용하게 되더군요.

우선 제 의도는 특정 IP 의 경우에만 무선 랜을 이용하고 나머지는 유선 랜을 이용해서 인터넷을 하기 위함
이었습니다. 이유는 아래의 상황 때문이었죠.

1. 상황은 이렇습니다.

유선 네트웍에는 사내 내부망이 연결되어 있고, 무선 네트웍에는 (공개된 AP의) 외부망으로 연결되어 있습니다.

문제는 내부망의 경우 특정 사이트의 접속을 막아 놓은 상태이기 때문에
MSN 메신저와 네이트온을 포함한 여러 메신저 접속 및 그 외 몇몇 사이트에 접근할 수 없었던 거죠.

서버 접속이나 업무를 위해서는 내부망을  반드시 이용할 수 밖에 없는 실정이다 보니,
기존에는 proxy server (HTTP Tunnel, Sconnect 등의 프로그램을 포함해서) 를 이용하는 방법을
사용했습니다.
가정에 proxy server 를 구축해둘 여유도 없고, 기타 위의 프로그램들도 유료이다 보니
(무료로 사용할 때에 Http Tunnel 은 속도가 조금 느릴 수 있는 제약이 있고, Sconnect 는 1일 1시간으로 제한)

아무튼 우연히 사무실에서 무선 네트웍이 (공개된ap) 잡히는 걸 알게 되었고
동시 사용을 시도해 보았으나, 실패.

결국, 내부망 로컬연결 - 사용한함 시켜놓고 무선랜쓰다가 다시 내부망 켜서 작업하고···.
이렇게 수동 ON/OFF 번갈아 가면서 필요할 때에만 무선으로 연결해서 쓰고 했는데 그리 효율적이지도
못하고 해서···.

유선·무선 둘 다 켜놓고 특정 IP 만 무선으로 이용하는 방법을 써서 사용하고 있습니다.

네이버와 구글을 포함해서 각종 검색사이트에 이리저리 검색해봤지만, 제가 원하는 답은
찾을 수 없더군요. 다만 비슷한 답들을 힌트로 -_-;

원리는, 라우팅 테이블을 건드려서 해당 IP 의 게이트웨이를 바꿔주는 방식인데,
말은 좀 어려운 것 같은데 해보면 간단합니다.


2. 의도

내부망으로는 업무/서버접속등을 위해 사용하고, 무선랜으로는 메신저 및 특정 사이트를
이용합니다.


3. 필요한 것

한대의 PC 와 두 개 이상의 네트워크.
- 이 글에서는 특정 사이트가 차단되어 있는 내부망 랜과 그외 무선 외부망을 기준으로 설명하고 있음.


4. 방법

    1) 2 개의 네트워크를 연결해 둡니다.

    2) 콘솔창을 띄우고, route print 명령으로 해당 Gateway 의 Metric 을 확인해 둠
      여기서 해당 Gateway 란 특정 사이트를 이용할 네트웍의 Gateway 를 말합니다.
       제 경우는, 내부망에서는 특정 차단된 사이트를 이용할 무선랜의 Gateway 가 해당됨.

            C:\ 콘솔> route print


    3) route add 명령을 이용해서 접속할 사이트를, 해당 Gateway 로 지정하는 명령을 실행해 줍니다.

            C:\ 콘솔> route add 명령 [접속할 사이트의 IP] [사용할 Gateway] [해당 metric]

   
    ※ route 명령만으로 실행하면 각종 도움말을 얻을 수 있음.

     4) route print 명령 또는 netstat -nr 명령으로 확인합니다.

    끝입니다.

이렇게 하면 route add 명령으로, 무선랜의 게이트웨이는 특정의 IP 만을 이용하게 되는 거죠.

하나의 예를 들어 보면, 내부망이 아닌 무선랜으로 네이트온을 접속할 경우에는

C:\ 콘솔> route add 203.226.253.91 192.168.1.1 METRIC 25
C:\ 콘솔> route add 203.226.253.73 192.168.1.1 METRIC 25


명령으로 가능하게 됩니다. (앞의 주소는 네이트온, 뒤에는 무선 게이트웨이)

참조 ) 네이트온 접속 주소

MSN 메신저의 경우는 이용 포트번호 말고도, 유동적으로 터널링되는 주소가 바뀌기 때문에
특정하기가 좀 어려워서 접속시마다 추가해 줬더니 약 20개 정도의 주소나 이용되어지더군요. -_-;

아참, 덤으로 이용되어지는 IP 주소를 알기 위해서는 netstat -na 명령으로 검색하면 됩니다.

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

위에 언급된 바와 같이 네트워크상의 특정 프로그램이 사용하고 있는 IP, port등을 알기 위해서는 netstat -an 명령을 이용하면 된다.


command 창에서 명령 수행 후

 TCP    172.21.29.246:1807     192.168.13.30:443      ESTABLISHED

요런 형태의 'ESTABLISHED' 상태의 연결들이 그것들이다.


출처: http://kongmks.cafe24.com/255?TSSESSION=67b637ce36321a49433071bc2dd63289