[질문]OpenSSL로 구현된 서버와 자바 클라이언트 통신

lhuijae의 이미지

제가 아직 잘 몰라서 그러는데요.. 두개의 예제 소스가 있습니다.. 하나는 서버, 다른 하나는 클라이언트 OpenSSL을 사용해서 통신합니다..
이 두개의 예제는 인터넷에서 받은 소스입니다.. 그리고 이 둘사이의 통신에 아무 문제도 없습니다.. 문제는 클라이언트를 자바로 하려고 하는데 자꾸 에러 메시지가 네요.. 아시는분은 리플부탁드립니다..

서버(serv.c)

/* serv.cpp  -  Minimal ssleay server for Unix 
   30.9.1996, Sampo Kellomaki <sampo@iki.fi> */ 


/* mangled to work with SSLeay-0.9.0b and OpenSSL 0.9.2b 
   Simplified to be even more minimal 
   12/98 - 4/99 Wade Scholine <wades@mail.cybg.com> */ 

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <memory.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 

#include <openssl/rsa.h>       /* SSLeay stuff */ 
#include <openssl/crypto.h> 
#include <openssl/x509.h> 
#include <openssl/pem.h> 
#include <openssl/ssl.h> 
#include <openssl/err.h> 


/* define HOME to be dir for key and cert files... */ 
#define HOME "./" 

/* Make these what you want for cert & key files */ 
#define CERTF  HOME "server-req.pem" 
#define KEYF  HOME  "server-key.pem" 


#define CHK_NULL(x) if ((x)==NULL) exit (1) 
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); } 
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); } 

void main () 
{ 
    int err; 
    int listen_sd; 
    int sd; 
    struct sockaddr_in sa_serv; 
    struct sockaddr_in sa_cli; 
    size_t client_len; 

    SSL_CTX* ctx; 
    SSL*     ssl; 
    X509*    client_cert; 

    char*    str; 
    char     buf [4096]; 

    SSL_METHOD *meth; 

    /* SSL preliminaries. We keep the certificate and key with the context. */ 
    SSL_load_error_strings(); 
    SSLeay_add_ssl_algorithms(); 
    meth = TLSv1_server_method(); 

    // create a new SSL_CTX object as framework for TLS/SSL enabled functions 
    ctx = SSL_CTX_new (meth); 
    if (!ctx) { 
        ERR_print_errors_fp(stderr); 
        exit(2); 
    } 

    if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) { 
        ERR_print_errors_fp(stderr); 
        exit(3); 
    } 
    if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) { 
        ERR_print_errors_fp(stderr); 
        exit(4); 
    } 
    if (!SSL_CTX_check_private_key(ctx)) { 
        fprintf(stderr,"Private key does not match the certificate public key\n"); 
        exit(5); 
    } 




    /* Prepare TCP socket for receiving connections */ 

    // Create Internet Socket and Fill sockaddr_in 
    listen_sd = socket (AF_INET, SOCK_STREAM, 0);    
    CHK_ERR(listen_sd, "socket"); 

    memset (&sa_serv, '\0', sizeof(sa_serv)); 
    sa_serv.sin_family      = AF_INET; 
    sa_serv.sin_addr.s_addr = INADDR_ANY; 
    sa_serv.sin_port        = htons (1111);          /* Server Port number */ 

    // Bind 
    err = bind(listen_sd, (struct sockaddr*) &sa_serv, sizeof (sa_serv));                    
    CHK_ERR(err, "bind"); 

    // Listening 
    err = listen (listen_sd, 5);  
    CHK_ERR(err, "listen"); 

    // Accept 
    client_len = sizeof(sa_cli); 
    sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len); 
    CHK_ERR(sd, "accept"); 

    // Close Listening socket 
    close (listen_sd); 

    // Connected-client info. 
    printf ("Connection from %lx, port %d\n", 
    sa_cli.sin_addr.s_addr, sa_cli.sin_port); 



    // TCP connection is ready. Do server side SSL. 
    // create a new SSL structure for a connection 
    ssl = SSL_new (ctx);                     
    CHK_NULL(ssl); 

    // connect the SSL object with a file descriptor 
    SSL_set_fd (ssl, sd); 
    err = SSL_accept (ssl);    
    CHK_SSL(err); 

    // Get the cipher - opt  
    printf ("SSL connection using %s\n", SSL_get_cipher (ssl)); 

    // Get client's certificate (note: beware of dynamic allocation) - opt 
    client_cert = SSL_get_peer_certificate (ssl); 
    if (client_cert != NULL)  
    { 
        printf ("Client certificate:\n"); 

        str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0); 
        CHK_NULL(str); 
        printf ("\t subject: %s\n", str); 
        free (str); 

        str = X509_NAME_oneline (X509_get_issuer_name  (client_cert), 0, 0); 
        CHK_NULL(str); 
        printf ("\t issuer: %s\n", str); 
        free (str); 

        /* We could do all sorts of certificate verification stuff here before 
           deallocating the certificate. */ 

        X509_free (client_cert); 
    }  
    else 
    { 
        printf ("Client does not have certificate.\n"); 
    } 

    // DATA EXCHANGE - Receive message and send reply. 
    err = SSL_read (ssl, buf, sizeof(buf) - 1);        
    CHK_SSL(err); 

    buf[err] = '\0'; 
    printf ("Got %d chars:'%s'\n", err, buf); 

    err = SSL_write (ssl, "I hear you.", strlen("I hear you.")); 
    CHK_SSL(err); 

    /* Clean up. */ 
    close (sd); 
    SSL_free (ssl); 
    SSL_CTX_free (ctx); 
} 

클라이언트(cli.c)

/* cli.cpp  -  Minimal ssleay client for Unix 
   30.9.1996, Sampo Kellomaki <sampo@iki.fi> */ 

/* mangled to work with SSLeay-0.9.0b and OpenSSL 0.9.2b 
   Simplified to be even more minimal 
   12/98 - 4/99 Wade Scholine <wades@mail.cybg.com> */ 

#include <stdio.h> 
#include <memory.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <netdb.h> 

#include <unistd.h> 

#include <openssl/crypto.h> 
#include <openssl/x509.h> 
#include <openssl/pem.h> 
#include <openssl/ssl.h> 
#include <openssl/err.h> 


#define CHK_NULL(x) if ((x)==NULL) exit (1) 
#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); } 
#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2); } 

void print_x509(SSL *ssl) 
{ 
    char *ascii_cert; 
    X509 *cert = SSL_get_peer_certificate(ssl); 
    BIO *b; 
    BUF_MEM *bptr; 

    b = BIO_new(BIO_s_mem()); 

    if(X509_print(b, cert) > 0) 
    { 
        BIO_get_mem_ptr(b, &bptr); 
        ascii_cert = (char *)malloc(1 + bptr->length); 
        memcpy(ascii_cert, bptr->data, bptr->length); 
    } 
    else 
    { 
        ascii_cert = (char *)malloc(1024); 
        sprintf(ascii_cert, "This certificate has never been seen before and can't be shown\n"); 
    } 
    BIO_free(b); 

    /* X.509 인증서 출력 */ 
    printf("X.509:\n%s\n", ascii_cert); 
} 

void main (int argc, char **argv) 
{ 
    int err; 
    int sd; 
    struct sockaddr_in sa; 

    SSL_CTX* ctx; 
    SSL*     ssl; 
    X509*    server_cert; 

    char*    str; 
    char     buf [4096]; 
    char hello[80]; 

    SSL_METHOD *meth; 

    printf ("Message to send: "); 
    fgets (hello, 80, stdin); 

    SSLeay_add_ssl_algorithms(); 
    //meth = SSLv2_client_method(); 
    meth = TLSv1_client_method(); 
    SSL_load_error_strings(); 
    ctx = SSL_CTX_new (meth); 
    CHK_NULL(ctx); 
    CHK_SSL(err); 


    /////////////////////////////////////////////////////////////////////////////////////// 
    // Create a socket and connect to server using normal socket calls. 
    sd = socket (AF_INET, SOCK_STREAM, 0);   
    CHK_ERR(sd, "socket"); 

    memset (&sa, '\0', sizeof(sa)); 
    sa.sin_family      = AF_INET; 
    sa.sin_addr.s_addr = inet_addr ("203.247.40.139");   /* Server IP */ 
    sa.sin_port        = htons     (atoi(argv[1]));          /* Server Port number */ 

    // Normal-connect 
    err = connect(sd, (struct sockaddr*) &sa, sizeof(sa));      
    CHK_ERR(err, "connect"); 

    // Now we have TCP conncetion. Start SSL negotiation. 
    // create a new SSL structure for a connection 
    ssl = SSL_new (ctx);     
    CHK_NULL(ssl);     

    // connect the SSL object with a file descriptor 
    SSL_set_fd (ssl, sd); 

    // initiate the TLS/SSL handshake with an TLS/SSL server 
    err = SSL_connect (ssl);     
    CHK_SSL(err); 

    /*  
     * Following two steps are optional and not required for 
     * data exchange to be successful.  
     */ 

    printf ("SSL connection using %s\n", SSL_get_cipher (ssl)); 

    // Get server's certificate (note: beware of dynamic allocation) - opt  
    server_cert = SSL_get_peer_certificate (ssl);     
    CHK_NULL(server_cert); 
    print_x509(ssl); 

    /* 
    printf ("Server certificate:\n"); 
    str = X509_NAME_oneline (X509_get_subject_name (server_cert),0,0); 
    CHK_NULL(str); 
    printf ("\t subject: %s\n", str); 
    free (str); 

    str = X509_NAME_oneline (X509_get_issuer_name  (server_cert),0,0); 
    CHK_NULL(str); 
    printf ("\t issuer: %s\n", str); 
    free (str); 
    */ 

    /*  
     * We could do all sorts of certificate verification stuff here before 
     * deallocating the certificate.  
     */ 
    X509_free (server_cert); 

    /////////////////////////////////////////////////////////////////////////////////////// 
    // DATA EXCHANGE - Send a message and receive a reply. 
     
    //err = SSL_write (ssl, "Hello World!", strlen("Hello World!")); 
    //CHK_SSL(err);  
    err = SSL_write (ssl, hello, strlen(hello));   
    CHK_SSL(err); 

    err = SSL_read (ssl, buf, sizeof(buf) - 1);     
    CHK_SSL(err); 
    buf[err] = '\0'; 
    printf ("Got %d chars:'%s'\n", err, buf); 

    // send SSL/TLS close_notify 
    SSL_shutdown (ssl);   

    /* Clean up. */ 

    close (sd); 
    SSL_free (ssl); 
    SSL_CTX_free (ctx); 
} 

서버의 개인키와 셀프 사인된 인증서 입니다. 그리고 인증서의 패스워드는 abcd 입니다.

*server-key.pem

-----BEGIN RSA PRIVATE KEY----- 
Proc-Type: 4,ENCRYPTED 
DEK-Info: DES-EDE3-CBC,AA26BA50E01C1524 

oXXeC9GyPwvJxVyqRXROLXp5Ew5n/gS6+vpDXXSIsuE8RIk17Mtx1NpOGWxmQ/hd 
L9zAvDniOoavTyKyVI0VZx13A1RzptaSP1CqEBeQUlT5DU3IFhwdj8BRXfpaWrve 
NnCZiyvr5CNgSLg0pVvcUhI9CmQtj94bLN6KATbZ/FyQZTSkrN6kh1jBwHd04RvZ 
2YvxtuzevtxvLLHOvxCxocIYnPWJzViEyuKbz/co3ywZibFXrqu2Xpgrk3lHN21M 
ZXWPeVJ2DzAIWMhqjpOX98w0hLHvZHVWpiO09avH/wzR7YbCKZpwFZUdjcUuzETZ 
OzJO3p97mf9D64KbAOmq7h6Pme8pkT/io8Qe24XyaV0C7ca67t3J3NSBVmyPNgEP 
MsfTctk98FfKmOXD7fm1y5k4YZ7weDuDRs09KNFxn6sm94Q5ssQmaAPNCVZTpGSW 
p6/sDb1dU8/2lTFFU67tquwR679h2AouF/Ea0Sa2l0o8HfcAS8YJxp77+W2qB9Zt 
ymkSJlvX7s5qt4oBryTOyDKVFzmzksjJHaar7tRJ00fTh+AICxxQvfzUE82oH49R 
+07clHW7DCh4FMevvflSujfIChVIwvwg2Vr1b63QIp8tlZ0BiPAZH8TV6cPDROVQ 
5dWDQlcOrvfNsC1qI17kvn/N4ZzKyvdB4cEZh6xMH8UfFJ+qpNhJ1gwJFe9XI11z 
90hSa9lsFqBBw2sGmnN9QxKC1UpdvjoZV1VTBEqGWYDR4S1lx575gm77nF9XcJAr 
pW7Fs9qKLWi7trWQxI0ncKQ6DGuGbh/ctebgchKe/kIA/4E0nQjTcg== 
-----END RSA PRIVATE KEY----- 

*server-req.pem

-----BEGIN CERTIFICATE----- 
MIIDYjCCAsugAwIBAgIBADANBgkqhkiG9w0BAQQFADCBgzELMAkGA1UEBhMCQVUx 
EzARBgNVBAgTClNvbWUtU3RhdGUxDDAKBgNVBAcTA0ZvbzENMAsGA1UEChMETGFu 
ZDEMMAoGA1UECxMDRm9vMRYwFAYDVQQDEw1zbmFmdS5taXQuZWR1MRwwGgYJKoZI 
hvcNAQkBFg1mdWJvYkBtaXQuZWR1MB4XDTAwMTExMzAyMjgxMVoXDTAwMTIxMzAy 
MjgxMVowgYMxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMQwwCgYD 
VQQHEwNGb28xDTALBgNVBAoTBExhbmQxDDAKBgNVBAsTA0ZvbzEWMBQGA1UEAxMN 
c25hZnUubWl0LmVkdTEcMBoGCSqGSIb3DQEJARYNZnVib2JAbWl0LmVkdTCBnzAN 
BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtvnaO7XYscdlXoTwql5uHa5Vx1ecKZOc 
pSAqGQx4LnMGbRvnb+m2OxUZ3xFc8V1a2eKlUyTKoo0bebTeS5/BLBik47TjfUlw 
/P1hLYhIFZNb+o/g3ZeWG/9QZYs0favV+0iAoqpy/scHwHZg2Vnpjivsit543s+x 
uuWuD4fpUIsCAwEAAaOB4zCB4DAdBgNVHQ4EFgQUTkDDGu1osvRIZY/LlZdmRbAs 
rM0wgbAGA1UdIwSBqDCBpYAUTkDDGu1osvRIZY/LlZdmRbAsrM2hgYmkgYYwgYMx 
CzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMQwwCgYDVQQHEwNGb28x 
DTALBgNVBAoTBExhbmQxDDAKBgNVBAsTA0ZvbzEWMBQGA1UEAxMNc25hZnUubWl0 
LmVkdTEcMBoGCSqGSIb3DQEJARYNZnVib2JAbWl0LmVkdYIBADAMBgNVHRMEBTAD 
AQH/MA0GCSqGSIb3DQEBBAUAA4GBAEmPUSEShK6tHGdwPUvwYwp7cR0mwRNi3peB 
vu5nqwjCnCFaQaUdBfh/18kT5uEpGB48A/6BImov36Aiq9cq6dVNGQkVI0y/FJ0J 
28zSYrRHXGOS5qMoWRaqCabuYbDUsx/bvCr21ET948jMawdd8nq+3ungEQzlIZtO 
oWcmJYad 
-----END CERTIFICATE----- 

*컴파일

# gcc -o serv serv.c -lssl -lcrypto 
# gcc -o serv cli.c -lssl -lcrypto 

*실행

# ./serv 
Enter PEM pass phrase: abcd 

# ./cli 
Message to send: hello!! 

이번에는 자바 클라이언트 입니다.. 여기에서 에러가 나는데.. 봐주세요..^^;

*SunSSLSocketClient.java

import java.io.*; 
import java.net.*; 
import java.security.*; 
import javax.net.ssl.*; 

public class SunSSLSocketClient { 
    private static final String HOST = "127.0.0.1"; 
    private static final int    PORT = 1111; 
    private static String [] socketProtocolVersion = new String[] {"TLSv1"}; 

    public static void main(String [] args) throws Exception { 
        char [] passPhrase = "abcd1234".toCharArray(); 

        KeyStore keystore = KeyStore.getInstance("JKS"); 
        keystore.load(new FileInputStream(".keystore"), passPhrase); 

        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 
        tmf.init(keystore); 

        SSLContext context = SSLContext.getInstance("TLS"); 
        TrustManager [] trustManagers = tmf.getTrustManagers(); 

        context.init(null, trustManagers, null); 

        SSLSocketFactory sf = context.getSocketFactory(); 
        SSLSocket socket = (SSLSocket)sf.createSocket(HOST, PORT); 
        socket.setEnabledProtocols(socketProtocolVersion); 
     
        System.out.println(socket); 

        PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); 
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); 

        pw.println("Hello!!"); 
        String fromServer = br.readLine(); 
        System.out.println(fromServer); 
    } 
} 

책에보니까 보통 이렇게 하더라구요.. 이렇게 코드를 작성하고 keytool을 사용해서 키저장소를 만들었습니다..
# keytool -genkey -keystore .keystore
.....

자바 클라이언트 실행
# java SunSSLSocketClient

에러 메시지는 다음과 같습니다..

Exception in thread "main" javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: java.s 
ecurity.cert.CertificateExpiredException: NotAfter: Wed Dec 13 11:28:11 KST 2000 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.d(DashoA6275) 
    at com.sun.net.ssl.internal.ssl.AppInputStream.read(DashoA6275) 
    at sun.nio.cs.StreamDecoder$CharsetSD.readBytes(StreamDecoder.java:406) 
    at sun.nio.cs.StreamDecoder$CharsetSD.implRead(StreamDecoder.java:446) 
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:180) 
    at java.io.InputStreamReader.read(InputStreamReader.java:167) 
    at java.io.BufferedReader.fill(BufferedReader.java:136) 
    at java.io.BufferedReader.readLine(BufferedReader.java:299) 
    at java.io.BufferedReader.readLine(BufferedReader.java:362) 
    at SunSSLSocketClient.main(SunSSLSocketClient.java:35) 
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateExpiredException: NotAfter: Wed Dec 13 11:28:11 KS 
T 2000 
    at com.sun.net.ssl.internal.ssl.BaseSSLSocketImpl.a(DashoA6275) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.a(DashoA6275) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.a(DashoA6275) 
    at com.sun.net.ssl.internal.ssl.SunJSSE_az.a(DashoA6275) 
    at com.sun.net.ssl.internal.ssl.SunJSSE_az.a(DashoA6275) 
    at com.sun.net.ssl.internal.ssl.SunJSSE_ax.a(DashoA6275) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.a(DashoA6275) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.j(DashoA6275) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.a(DashoA6275) 
    at com.sun.net.ssl.internal.ssl.AppOutputStream.write(DashoA6275) 
    at sun.nio.cs.StreamEncoder$CharsetSE.writeBytes(StreamEncoder.java:334) 
    at sun.nio.cs.StreamEncoder$CharsetSE.implFlushBuffer(StreamEncoder.java:402) 
    at sun.nio.cs.StreamEncoder$CharsetSE.implFlush(StreamEncoder.java:406) 
    at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:150) 
    at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:213) 
    at java.io.BufferedWriter.flush(BufferedWriter.java:230) 
    at java.io.PrintWriter.newLine(PrintWriter.java:256) 
    at java.io.PrintWriter.println(PrintWriter.java:405) 
    at java.io.PrintWriter.println(PrintWriter.java:516) 
    at SunSSLSocketClient.main(SunSSLSocketClient.java:34) 
Caused by: java.security.cert.CertificateExpiredException: NotAfter: Wed Dec 13 11:28:11 KST 2000 
    at sun.security.x509.CertificateValidity.valid(CertificateValidity.java:268) 
    at sun.security.x509.X509CertImpl.checkValidity(X509CertImpl.java:524) 
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.a(DashoA6275) 
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.a(DashoA6275) 
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(DashoA6275) 
    at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(DashoA6275) 
 ... 17 more 

아직 개념을 잘 몰라서 내용이 두서없습니다.. 몇칠째 해결 못하고 있습니다.. 도와주세요...[/code]

File attachments: 
첨부파일 크기
Package icon examples.zip7.44 KB
xiphoid의 이미지

아 피곤해

아 피곤해

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.