네트워크 관련 명령어

출처 : http://egloos.zum.com/yoontaesub/v/110992


ping 명령어

  : 네트워크 환경 장비들 간의 통신이 잘 되고 있는지 확인하는 명령어. ICMP 프로토콜을

   이용하여 로컬 호스트와 외부와의 통신이 이루어지고 있는지 테스트하기 위한 네트워크

   명령어로 결과값 중 TTL 값으로 사용되는 운영체제도 알 수 있음.

 - # ping [option] 호스트

            -c : ping 테스트 시 지정한 수만큼의 패킷을 보냄. 기본 무한

            -s : ping 테스트 시 보내는 패킷의 바이트 수를 지정. 기본 56Byte

            -i : ping 테스트 시 몇 초 간격으로 패킷을 보낼지 설정. 기본 1초

            -w : ping 테스트 시 패킷을 보내고 몇 초 후에 실행을 멈출것인지 설정


 - # ping -c 4 -i 2 192.168.1.32 ->192.168.1.32 호스트를 4개의 패킷, 2초 간격으로 패킷 전송

 


netstat 명령어

  : 라우팅과 관련된 정보를 얻기 위한 명령어. 라우팅 테이블을 화면에 표시.


 - # netstat -nr : 커널 라우팅 테이블을 10진수의 수치정보로 출력

 - # netstat -a | grep LISTEN : 열려 있는 포트를 출력 (= # netstat -atp)



traceroute 명령어

  : 네트워크 통신 경로를 확인하는 명령어로 패킷이 목적지까지 전달되는 경로를 확인하는

   명령어. ICMP를 이용하여 TTL값을 포함하고 있는 패킷을 전송하여 반환값을 출력.


 - # traceroute -i eth1 168.126.63.1 : 특정 인터페이스를 통해 목적지의 호스트까지 경로 확인



My traceroute 명령어

  : 콘솔 상에서의 traceroute와 동일한 GUI 환경에서의 네트워크 통신 경로 확인 명령어



rpcinfo 명령어

  : 한 프로그램이 네트워크 상의 다른 호스트의 프로그램에 서비스를 요청하는 데 사용

   되는 프로토콜인 RPC의 정보를 확인하는 명령어


 - # rpcinfo [ -n <포트번호> ] -u <호스트> <프로그램번호> [ <버전번호> ]

 - # rpcinfo [ -n <포트번호> ] -t 호스트 프로그램 번호 [ 버전번호 ]

 - # rpcinfo -p [ <호스트> ]

 - # rpcinfo -b 프로그램번호 버전번호

 - # rpcinfo -d 프로그램번호 버전번호



arp 명령어

  : IP 주소를 하드웨어 주소인 MAC 주소로 변경해 주는 명령어. ARP cache는 IP 주소와

   MAC 주소의 목록을 유지하는데 사용되는 메커니즘으로, 서로 간에 맵핑된 정보는

   cache에 잠시 동안 보관되는데 최근에 맵핑된 정보를 보기 위해 사용하는 명령어가 바

   로 arp임.


 - # arp [option] 호스트

          -a : 지정한 호스트에 대한 정보를 출력하며, 호스트를 지정하지 않을 경우에는 현재 캐시

               에 들어있는 모든 정보를 출력

          -s : 캐시에 저장된 특정 IP 주소에 대한 MAC Address 변경

          -d : 캐시에 저장된 특정 MAC Address 삭제

          -i : 지정한 네트워크 인터페이스의 ARP를 출력

 

블로그 이미지

레몬도리 LemonDory

개발자의 이야기

댓글을 달아 주세요

출처 : http://blog.daum.net/hypermax/6


*먼저 내 업무에서는 iptables와 hosts.allow 파일을 함께 이용 한다.

1. 방화벽 내용 넣고 > 방화벽 실행 > 방화벽 내용 저장

#cd /etc/sysconfig/

#vi iptables

(iptables 내용)

#service iptables restart

#/etc/init.d/iptables save

 

--------------▶ iptables 사용법

-기본 모두 막고 시작하기-
# iptables -F
# iptables -X
# iptables -P INPUT DROP
# iptables -P FORWARD DROP
# iptables -P OUTPUT DROP
-루프백 허용
-
# iptables -A INPUT -i lo -j ACCEPT
# iptables -A OUTPUT -o -lo -j ACCEPT

iptables [-t table] command [match] [target\jump]

 

-A(--append)            : 규칙을 추가한다.

-N(--new-chain)        : 새로운 체인 생성

-X(--delete-chain)     : 체인 제거

-P(--policy)              : 체인 기본정책 변경

-L(--list)                  : 체인의 규칙상태 보기

-F(--flush)               : 체인내의 모든 규칙 제거(방화벽 초기화)

-Z(--zero)                : 체인내의 모든 규칙의 패킷과 바이트의 카운트를 0으로 초기화

-D(--delete)             : 규칙을 삭제

-R(--replace)            : 새로운 규칙으로 대체

-I(--insert)               : 체인의 가장 처음에 규칙을 추가한다.

-E(--rename-chain)    : 체인의 이름을 변경한다.

 

 

2) iptables 체인 종류

INPUT : 로컬로 들어오는 패킷(입력 패킷)

FORWARD : INPUT와 OUTPUT 역할, 라우터에 방화벽을 적용할 때 쓰임

OUTPUT : 외부로 나가는 패킷(출력 패킷)

 

INPUT 체인에 사용자 정의로 체인을 추가하여 INPUT 체인 대신에 사용할 수 있는데, 페도라 코어의 경우는 RH-Firewall-1-INPUT라는 사용자 정의 체인을 사용한다. 3개의 기본 체인(INPUT, OUTPUT, FORWARD)은 수정이나 삭제가 불가능하며, 사용자 정의 체인은 다음과 같은 방법으로 생성해 줄 수 있다.

 

 

 

 

3) iptables 다루기

 

▶ 방화벽 정책 초기화

# iptables -F

# iptables -X

# iptables -Z

 

 

▶ 기본 정책 설정

# iptables -P INPUT DROP

# iptables -P OUTPUT DROP

# iptables -P FORWARD DROP

 

 

▶ 사용자 정의 체인 생성 및 INPUT 체인에 추가

# iptables -N 사용자정의체인명

# iptables -A INPUT -j 사용자정의체인명

 

 

▶ 허용 정책 설정

루프백 접속 허용

다른 곳과 네트워크가 연결되어 있지 않더라도 시스템의 기본 네트워크이며 로컬 호스트의 인터페이스인 루프백에 대해서는 접속이 이뤄질 수 있도록 해야 하므로, 다음과 같이 설정한다.

iptables -A INPUT -i lo -j ACCEPT

iptables -A OUTPUT -o lo -j ACCEPT

 

 

내부 네트워크 접속

iptables -A fedora -s 192.168.0.0/24 -d 192.168.0.0/24 -j ACCEPT

iptables -A OUTPUT -s 192.168.0.0/24 -d 192.168.0.0/24 -j ACCEPT

 

 

내부 -> 외부 접속

iptables -A fedora -s 외부주소 -p tcp -m tcp --sport 포트번호 -j ACCEPT

iptables -A OUTPUT -d 외부주소 -p tcp -m tcp --dport 포트 -j ACCEPT

 

 

① DNS 포트 허용

iptables -A fedora -p udp -m udp --sport 53 -j ACCEPT

iptables -A OUTPUT -p udp -m udp --dport 53 -j ACCEPT

 

② ICMP 핑 허용

iptables -A OUTPUT -o eth0 -p icmp --icmp-type echo-request -j ACCEPT

iptables -A fedora -i eth0 -p icmp --icmp-type echo-reply -j ACCEPT

iptables -A OUTPUT -o eth0 -p icmp --icmp-type echo-reply -j ACCEPT

 

③ SSH 포트 허용 ( 192.168.0.1 -> 172.16.1.20)

iptables -A fedora -s 172.16.1.20 -p tcp -m tcp --sport 22 -j ACCEPT

iptables -A OUTPUT -d 172.16.1.20 -p tcp -m tcp --dport 22 -j ACCEPT

 

④ HTTP 포트 허용

iptables -A fedora -i eth0 -p tcp -m tcp --sport 80 --dport 1024:65535 -j ACCEPT

iptables -A OUTPUT -o eth0 -p tcp -m tcp --sport 1024:65535 --dport 80 -j ACCEPT

 

⑤ FTP 포트 허용

명령(제어) 포트(tcp 21) 접속

iptables -A fedora -i eth0 -p tcp -m tcp --sport 21 --dport 1024:65535 -j ACCEPT

iptables -A OUTPUT -o eth0 -p tcp -m tcp --sport 1024:65535 --dport 21 -j ACCEPT

*데이터 포트(tcp20) 접속(능동 모드 접속)

iptables -A fedora -i eth0 -p tcp -m tcp --sport 21 --dport 1024:65535 -j ACCEPT

iptables -A OUTPUT -o eth0 -p tcp -m tcp --sport 1024:65535 --dport 21 -j ACCEPT

*데이터 포트(tcp 1024이상의 포트) (Passive 모드 접속)

iptables -A fedora -i eth0 -p tcp -m tcp --sport 1024:65535 --dport 1024:65535 -j ACCEPT

iptables -A OUTPUT -o eth0 -p tcp -m tcp --sport 1024:65535 --dport 1024:65535 -j ACCEPT

 

 

외부 -> 내부 접속

① SSH 포트 허용

iptables -A fedora -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT

iptables -A OUTPUT -o eth0 -p tcp -m tcp --sport 22 -j ACCEPT

 

② http 포트 허용

iptables -A fedora -i eth0 -p tcp -m tcp --dport 80 -j ACCEPT

iptables -A OUTPUT -o eth0 0p tcp -m tcp --sport 80 -j ACCEPT

 

③ ftp 포트 허용 ( passive mode)

iptables -A fedora -i eth0 -p tcp -m tcp --dport 21 -j ACCEPT

iptables -A OUTPUT -o eth0 -p tcp -m tcp --sport 21 -j ACCEPT

 

iptables -A fedora -i eth0 -p tcp -m tcp --dport 1024:65535 -j ACCEPT

iptables -A OUTPUT -o eth0 -p tcp -m tcp --sport 1024:65535 -j ACCEPT

 

 

예제 :

중국발 해킹을 통하여 웹서버를 공격하고 있다는 사실을 알았다.
  찾아낸 IP는 10.10.1.1 ~ 10.10.1.255, 10.10.2.3, 10.10.3.5 와 같으며 접근통제정책을 통하여

  위의 IP에 대하여 web 접속을 거부하라. 단, 10.10.1.33 IP는 web 접속을 허락하여야 한다.

/sbin/iptables -A INPUT -s 10.10.1.33  -p tcp --dport 80 -j ACCEPT

/sbin/iptables -A INPUT -s 10.10.1.1/10.10.1.255  -p tcp --dport 80 -j DROP

/sbin/iptables -A INPUT -s 10.10.2.3  -p tcp --dport 80 -j DROP

/sbin/iptables -A INPUT -s 10.10.3.5  -p tcp --dport 80 -j DROP

 

/sbin/iptables -A INPUT -s 202.190.123.68  -p tcp --dport 21 -j DROP

 

/sbin/iptables -A INPUT -s 118.217.12.35  -p tcp --dport 1:65535 -j DROP

- PING 명령어는 서버 내부에서는 사용가능해야 하며, 192.168.1.13, 192.168.1.11 IP를 제외하고는
  모두 거부하라.

 

/sbin/iptables -A INPUT -s 192.168.1.13 -p icmp --icmp-type echo-request  -j ACCEPT

/sbin/iptables -A INPUT -s 192.168.1.11 -p icmp --icmp-type echo-request  -j ACCEPT

/sbin/iptables -A INPUT  -p icmp --icmp-type echo-request  -j DROP

 

- 110포트와 143포트는 localhost와 192.168.1.13, 192.168.1.11 에서는 허용하고
   외부에서는 차단하라.

 

/sbin/iptables -A INPUT -s 192.168.1.13  -p tcp --dport 110 -j ACCEPT

/sbin/iptables -A INPUT -s 192.168.1.11  -p tcp --dport 110 -j ACCEPT

/sbin/iptables -A INPUT -p tcp -m tcp --dport 110 -j DROP

 

/sbin/iptables -A INPUT -p tcp -m tcp --dport 110 -j DROP

 

/sbin/iptables -A INPUT -s 192.168.1.13  -p tcp --dport 143 -j ACCEPT

/sbin/iptables -A INPUT -s 192.168.1.11  -p tcp --dport 143 -j ACCEPT

/sbin/iptables -A INPUT -p tcp -m tcp --dport 143 -j DROP

 

- ssh와 ftp에 대해서는 iptables 를 통하여 문제 2번에 해당하는 정책을 사용하여 똑 같이 적용하라.

/sbin/iptables -A INPUT -s 192.168.0.0/24  -p tcp --dport 22 -j ACCEPT

/sbin/iptables -A INPUT -s 192.168.1.13  -p tcp --dport 22 -j ACCEPT

/sbin/iptables -A INPUT -s 192.168.1.11  -p tcp --dport 22 -j ACCEPT

/sbin/iptables -A INPUT -p tcp -m tcp --dport 22 -j

 

개요

설치

솔라리스 10의 경우는 설치할 필요 없다. (이미 설치되어있다) 여기서는 솔라리스 9 이하를 기준으로 설명한 것이다.

·         설치

·         root@wl ~ # wget http://coombs.anu.edu.au/~avalon/ip_fil4.1.33.tar.gz
·         root@wl ~ # wget http://coombs.anu.edu.au/~avalon/pfil-2.1.13.tar.gz
·         root@wl ~ # tar xvfz ip_fil4.1.33.tar.gz
·         root@wl ~ # tar xvfz pfil-2.1.13.tar.gz
·         root@wl ~ # cd pfil
·         root@wl ~/pfil # /usr/ccs/bin/make SunOS32 1)
·         root@wl ~/pfil # /usr/ccs/bin/make package 1)
·         root@wl ~/pfil # pkgadd -d /tmp/pfil.pkg 2)
·         root@wl ~/pfil # ifconfig -a
·         lo0: flags=1000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4> mtu 8232 index 1
·                 inet 127.0.0.1 netmask ff000000
·         pcn0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
·                 inet 192.168.0.11 netmask ffffff00 broadcast 192.168.0.255
·                 ether 0:c:29:d4:e0:bd
·         root@wl ~/pfil # cat /etc/opt/pfil/iu.ap 3)
·                 pcn     -1      0       pfil
·         root@wl ~/pfil # cd ..
·         root@wl ~ # cd ip_fil4.1.33
·         root@wl ~/ip_fil4.1.33 # /usr/ccs/bin/make solaris
·         root@wl ~/ip_fil4.1.33 # cd SunOS5
·         root@wl ~/ip_fil4.1.33/SunOS5 # /usr/ccs/bin/make package 4)
·         root@wl ~/ip_fil4.1.33/SunOS5 # sync; sync; reboot 5)

1) 반드시 /usr/ccs/bin/make 를 사용한다. 만약 gnu make를 사용하고 있으면 컴파일이 되지 않는다. 64bit 솔라리스를 사용하고 있다면 32대신 64를 입력한다.
2) 자동으로 설치되는 것이 아니라 패키지파일이 생성된다. 패키지 파일은 그냥 설치해주면 된다.
3) 패키지 파일을 인스톨 한 후 /etc/opt/pfil/iu.ap 파일을 확인한다. 시스템에 설치되어있는 NIC 종류별로 (lo제외) 한줄씩 /etc/opt/pfil/iu.ap에 등록되어있어야 한다. 같은 종류의 NIC가 두개 설치되어 있어도 한 종류이므로 한 줄만 들어가게 된다.
4) make package하면 자동으로 패키지가 생성되고 인스톨 된다. (SunOS5디렉토리에 ipf.pkg 파일이 생성된다) 바이너리는 /opt/ipf에, 설정파일은 /etc/opt/ipf에 있다.
5) pfil 을 설치한 후, 반드시 재시작해야 한다. (ipf 때문에 재시작하는 것이 아니다)

·         실행

재시작 하면 IPFilter 가 이미 실행되어있을 것이다. 아래는 제대로 설치되었는지 확인하기 위함이다.

root@wl ~ # /etc/init.d/ipfboot start 1)
Set 0 now inactive
filter sync'd
0 entries flushed from NAT table
0 entries flushed from NAT list
filter sync'd
root@wl ~ # ndd /dev/pfil qif_status 2)
ifname ill q OTHERQ ipmp num sap hl nr nw bad copy copyfail drop notip nodata notdata
QIF1 0x0 0xd40d2cf0 0xd40d2d74 0x0 1 806 0 3 14 0 0 0 0 0 0 0
pcn0 0xd3c49a9c 0xd4054180 0xd4054204 0x0 0 800 14 695 572 0 0 0 0 0 0 0
root@wl ~/pfil # strconf < /dev/pcn 2)
pfil
pcn
root@wl ~ #

1) 시작하기. /etc/rc2.d/S65ipfboot에 등록되어있다.
2) pfil장치와 이에 연결된 pcn 디바이스(시스템마다 다르다)에 IPFilter가 제대로 연결되어있는지 확인한다.

블로그 이미지

레몬도리 LemonDory

개발자의 이야기

댓글을 달아 주세요

SslStream 클래스

https://msdn.microsoft.com/ko-kr/library/system.net.security.sslstream(v=vs.110).aspx

참고하기(채팅) : http://it-jerryfamily.tistory.com/entry/Program-C-SslStream-%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%ED%86%B5%EC%8B%A0-%EB%B0%A9%EB%B2%95


샘플 코드를 Mono를 이용해서 Debian에 올릴 일이 있어서 테스를 진행하다 아래와 같은 오류를 해결하려고 애쓰고 있었습니다..

System.IO.IOException: The authentication or decryption has failed. ---> Mono.Security.Protocol.Tls.TlsException: Server certificate Private Key unavailable. 


SSL 파일도 바꿔보고

암호도 바꿔보고 발급자, 발급 대상에 특수문자가 있어서 테스트 인증서를 재발급 해보고...

구글을 한참 두지다가 발견한 것을 공유합니다. 


너무 간단해서....

민망하지만 일단 인증서 발급부터 쭉 진행하겠습니다.


1. 인증서 발급

 makecert -r -pe -n "CN=test" -b 01/01/2016 -e 01/01/2030 -sky exchange -ss my

!! makecert.exe 파일의 경로는 C:\Program Files (x86)\Windows Kits\10\bin\x64 입니다.

전 윈도우 10이라 C:\Program Files (x86)\Windows Kits\10폴더에 있는 녀석으로 했습니다.

윈도우 버전 별로 폴더가 있습니다. 윈도우 10은 8.0, 8.1, 10 이렇게 있네요


2. 인증서 등록

시작 - 실행 - certmgr(윈도우 10은 검색에 "사용자 인증서 관리")

아래의 경로에 인증서 발급 내역이 있습니다. Test 인증서가 보입니다.


인증서를 선택하고 더블클릭으로 정보를 볼 수 있습니다.

일반 탭과 인증 경로 탭에 빨간 상자를 보시면 인증서가 신뢰를 얻지 못했다고 나옵니다.


올바른 인증서를 만들기 위해서 아래를 따라 진행하시면 됩니다.

"test"로 등록된 인증서를 선택하고 오른쪽 마우스로 Drag ->신뢰할 수 있는 루트 인증 기관 - 인증서에 놓기 - 여기에 복사


경고창이 뜹니다.

확인으로 복사를 해줍니다.


완료되었다면 아래와 같은 인증서 정보를 확인 가능합니다.

이제 인증서는 완료되었습니다.


2. 인증서 파일로 저장하기

위에서 인증서를 만들어 보았습니다.

이제 인증서를 파일로 만들어야 합니다.

자! 시작하죠

인증서를 선택하고 오른쪽 마우스 클릭! -> 모든 작업 -> 내보내기


인증서 내보내기 마법사

순서대로 진행합니다.

암호는 필수로 입력하고 기억하세요!


내보내기가 완료되었습니다.


3. 소스

이제 소스 작성을 해봅시다.

윈도우에서 테스트를 해보실 분은 솔루션을 만들고 프로젝트를 두개 만듭니다.


SslServer.cs

 using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.IO;


namespace Examples.System.Net
{
    public sealed class SslTcpServer
    {
        static X509Certificate2 serverCertificate = null;
        // The certificate parameter specifies the name of the file
        // containing the machine certificate.
        public static void RunServer(string certificate)
        {
            serverCertificate = new X509Certificate2(certificate, "password");
            // Create a TCP/IP (IPv4) socket and listen for incoming connections.
            IPAddress ipAddress = IPAddress.Parse("0.0.0.0");
            IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, 8888);

            TcpListener listener = new TcpListener(ipLocalEndPoint);

            listener.Start();
            while (true)
            {
                Console.WriteLine("Waiting for a client to connect...");
                // Application blocks while waiting for an incoming connection.
                // Type CNTL-C to terminate the server.
                TcpClient client = listener.AcceptTcpClient();
                ProcessClient(client);
            }
        }
        static void ProcessClient(TcpClient client)
        {
            // A client has connected. Create the
            // SslStream using the client's network stream.
            SslStream sslStream = new SslStream(
                client.GetStream(), false);
            // Authenticate the server but don't require the client to authenticate.
            try
            {
                sslStream.AuthenticateAsServer(serverCertificate,
                    false, SslProtocols.Tls, true);
                // Display the properties and settings for the authenticated stream.
                DisplaySecurityLevel(sslStream);
                DisplaySecurityServices(sslStream);
                DisplayCertificateInformation(sslStream);
                DisplayStreamProperties(sslStream);

                // Set timeouts for the read and write to 5 seconds.
                sslStream.ReadTimeout = 5000;
                sslStream.WriteTimeout = 5000;
                // Read a message from the client.  
                Console.WriteLine("Waiting for client message...");
                string messageData = ReadMessage(sslStream);
                Console.WriteLine("Received: {0}", messageData);

                // Write a message to the client.
                byte[] message = Encoding.UTF8.GetBytes("Hello from the server.<EOF>");
                Console.WriteLine("Sending hello message.");
                sslStream.Write(message);
            }
            catch (AuthenticationException e)
            {
                Console.WriteLine("Exception: {0}", e.Message);
                if (e.InnerException != null)
                {
                    Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
                }
                Console.WriteLine("Authentication failed - closing the connection.");
                sslStream.Close();
                client.Close();
                return;
            }
            finally
            {
                // The client stream will be closed with the sslStream
                // because we specified this behavior when creating
                // the sslStream.
                sslStream.Close();
                client.Close();
            }
        }
        static string ReadMessage(SslStream sslStream)
        {
            // Read the  message sent by the client.
            // The client signals the end of the message using the
            // "<EOF>" marker.
            byte[] buffer = new byte[2048];
            StringBuilder messageData = new StringBuilder();
            int bytes = -1;
            do
            {
                // Read the client's test message.
                bytes = sslStream.Read(buffer, 0, buffer.Length);

                // Use Decoder class to convert from bytes to UTF8
                // in case a character spans two buffers.
                Decoder decoder = Encoding.UTF8.GetDecoder();
                char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                decoder.GetChars(buffer, 0, bytes, chars, 0);
                messageData.Append(chars);
                // Check for EOF or an empty message.
                if (messageData.ToString().IndexOf("<EOF>") != -1)
                {
                    break;
                }
            } while (bytes != 0);

            return messageData.ToString();
        }
        static void DisplaySecurityLevel(SslStream stream)
        {
            Console.WriteLine("Cipher: {0} strength {1}", stream.CipherAlgorithm, stream.CipherStrength);
            Console.WriteLine("Hash: {0} strength {1}", stream.HashAlgorithm, stream.HashStrength);
            Console.WriteLine("Key exchange: {0} strength {1}", stream.KeyExchangeAlgorithm, stream.KeyExchangeStrength);
            Console.WriteLine("Protocol: {0}", stream.SslProtocol);
        }
        static void DisplaySecurityServices(SslStream stream)
        {
            Console.WriteLine("Is authenticated: {0} as server? {1}", stream.IsAuthenticated, stream.IsServer);
            Console.WriteLine("IsSigned: {0}", stream.IsSigned);
            Console.WriteLine("Is Encrypted: {0}", stream.IsEncrypted);
        }
        static void DisplayStreamProperties(SslStream stream)
        {
            Console.WriteLine("Can read: {0}, write {1}", stream.CanRead, stream.CanWrite);
            Console.WriteLine("Can timeout: {0}", stream.CanTimeout);
        }
        static void DisplayCertificateInformation(SslStream stream)
        {
            Console.WriteLine("Certificate revocation list checked: {0}", stream.CheckCertRevocationStatus);

            X509Certificate localCertificate = stream.LocalCertificate;
            if (stream.LocalCertificate != null)
            {
                Console.WriteLine("Local cert was issued to {0} and is valid from {1} until {2}.",
                    localCertificate.Subject,
                    localCertificate.GetEffectiveDateString(),
                    localCertificate.GetExpirationDateString());
            }
            else
            {
                Console.WriteLine("Local certificate is null.");
            }
            // Display the properties of the client's certificate.
            X509Certificate remoteCertificate = stream.RemoteCertificate;
            if (stream.RemoteCertificate != null)
            {
                Console.WriteLine("Remote cert was issued to {0} and is valid from {1} until {2}.",
                    remoteCertificate.Subject,
                    remoteCertificate.GetEffectiveDateString(),
                    remoteCertificate.GetExpirationDateString());
            }
            else
            {
                Console.WriteLine("Remote certificate is null.");
            }
        }
        private static void DisplayUsage()
        {
            Console.WriteLine("To start the server specify:");
            Console.WriteLine("serverSync certificateFile.cer");
            Environment.Exit(1);
        }
        public static int Main(string[] args)
        {
            string certificate = null;
            if (args == null || args.Length < 1)
            {
                DisplayUsage();
            }
            certificate = args[0];
            //certificate = @"Test.pfx";   //윈도우에서 테스트로 진행할 때 사용함 위에 args 파라미터 체크는 주석
            SslTcpServer.RunServer(certificate);
            return 0;
        }
    }
}


SslClient.cs

 using System;
using System.Collections;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Text;
using System.Security.Cryptography.X509Certificates;
using System.IO;

namespace Examples.System.Net
{
    public class SslTcpClient
    {
        private static Hashtable certificateErrors = new Hashtable();

        // The following method is invoked by the RemoteCertificateValidationDelegate.
        public static bool ValidateServerCertificate(
              object sender,
              X509Certificate certificate,
              X509Chain chain,
              SslPolicyErrors sslPolicyErrors)
        {
            if (sslPolicyErrors == SslPolicyErrors.None)
                return true;

            Console.WriteLine("Certificate error: {0}", sslPolicyErrors);

            // Do not allow this client to communicate with unauthenticated servers.
            return false;
        }
        public static void RunClient(string machineName, string serverName)
        {
            // Create a TCP/IP client socket.
            // machineName is the host running the server application.
            TcpClient client = new TcpClient(machineName, 8888);
            Console.WriteLine("Client connected.");
            // Create an SSL stream that will close the client's stream.
            SslStream sslStream = new SslStream(
                client.GetStream(),
                false,
                new RemoteCertificateValidationCallback(ValidateServerCertificate),
                null
                );
            // The server name must match the name on the server certificate.
            try
            {
                sslStream.AuthenticateAsClient(serverName);
            }
            catch (AuthenticationException e)
            {
                Console.WriteLine("Exception: {0}", e.Message);
                if (e.InnerException != null)
                {
                    Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
                }
                Console.WriteLine("Authentication failed - closing the connection.");
                client.Close();
                return;
            }
            // Encode a test message into a byte array.
            // Signal the end of the message using the "<EOF>".
            byte[] messsage = Encoding.UTF8.GetBytes("Hello from the client.<EOF>");
            // Send hello message to the server.
            sslStream.Write(messsage);
            sslStream.Flush();
            // Read message from the server.
            string serverMessage = ReadMessage(sslStream);
            Console.WriteLine("Server says: {0}", serverMessage);
            // Close the client connection.
            client.Close();
            Console.WriteLine("Client closed.");
        }
        static string ReadMessage(SslStream sslStream)
        {
            // Read the  message sent by the server.
            // The end of the message is signaled using the
            // "<EOF>" marker.
            byte[] buffer = new byte[2048];
            StringBuilder messageData = new StringBuilder();
            int bytes = -1;
            do
            {
                bytes = sslStream.Read(buffer, 0, buffer.Length);

                // Use Decoder class to convert from bytes to UTF8
                // in case a character spans two buffers.
                Decoder decoder = Encoding.UTF8.GetDecoder();
                char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                decoder.GetChars(buffer, 0, bytes, chars, 0);
                messageData.Append(chars);
                // Check for EOF.
                if (messageData.ToString().IndexOf("<EOF>") != -1)
                {
                    break;
                }
            } while (bytes != 0);

            return messageData.ToString();
        }
        private static void DisplayUsage()
        {
            Console.WriteLine("To start the client specify:");
            Console.WriteLine("clientSync machineName [serverName]");
            Environment.Exit(1);
        }
        public static int Main(string[] args)
        {
            string serverCertificateName = null;
            string machineName = null;
            if (args == null || args.Length < 1)
            {
                DisplayUsage();
            }
            // User can specify the machine name and server name.
            // Server name must match the name on the server's certificate. 
            machineName = args[0];

            if (args.Length < 2)
            {
                serverCertificateName = machineName;
            }
            else
            {
                serverCertificateName = args[1];
            }
            //serverCertificateName = "Test";
            //machineName = "192.168.0.20";
            SslTcpClient.RunClient(machineName, serverCertificateName);
            return 0;
        }
    }
}


4. 리눅스에 소스 반영 및 빌드 후 실행

소스가 준비가 되었다면 리눅스 사이트에 접속합니다.


FTP로 파일을 올려봅니다.

FileZilla를 다운 받아 서버에 접속 후 적당한 경로에 파일을 올립니다. (꼭 FileZilla가 아니어도 됩니다.)


Putty나 기타 SSH툴로 접속합니다.

실행을 위해 빌드 해보겠습니다.


SslServer.cs

mcs SslServer.cs


SslClient.cs

mcs SslClient.cs 


Putty를 두개 띄워줍니다.

한쪽에는 서버 한쪽에는 클라이언트를 실행합니다.


Server

 mono SslServer.exe Test.pfx


Client

 mono SslClient.exe


서버에 클라이언트가 잘 붙고 Log가 잘 찍히나요?

제대로 안 되신다면 댓글 달아주시면 알려드리겠습니다.


참! 여기에서 포인트는 화이트페이퍼에 나온 코드로는 정상 작동이 안됩니다.

해결 방법은 X509Certificate X509Certificate2로 변경하시면 됩니다!!!




블로그 이미지

레몬도리 LemonDory

개발자의 이야기

댓글을 달아 주세요