⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tlsserver.cxx

📁 现在应用最广泛的一种私网穿透方式
💻 CXX
字号:
/*    This program takes no arguments. It opens the STUN tcp port and rus a tls server   on it. */#include <sys/types.h>#include <string.h>#include <openssl/e_os2.h>#include <openssl/evp.h>#include <openssl/crypto.h>#include <openssl/err.h>#include <openssl/pem.h>#include <openssl/pkcs7.h>#include <openssl/x509.h>#include <openssl/x509v3.h>#include <openssl/ssl.h>#ifdef WIN32#include <errno.h>#include <winsock2.h>#include <io.h>#endif #ifndef WIN32#include <sys/types.h>#include <sys/time.h>#include <sys/socket.h>#include <sys/select.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#endif#ifdef WIN32# include <windows.h># include <winbase.h># include <errno.h># include <winsock2.h># include <io.h>typedef unsigned int u_int32_t;#endif#include <cassert>#include <fcntl.h>#include <iostream>#include <cstdlib>#include <stdio.h>#ifdef __MACH__typedef int socklen_t;#endif#include "stun.h"using namespace std;#define MAX_CONNECTIONS 64#ifdef WIN32typedef int socklen_t;//#define errno WSAGetLastError()typedef SOCKET Socket;#elsetypedef int Socket;static const Socket INVALID_SOCKET = -1;static const int SOCKET_ERROR = -1;#endif// TODO - !cj! - need to deal with closing connections void makeSocketNonBlocking(Socket fd){#if WIN32   unsigned long noBlock = 1;   int errNoBlock = ioctlsocket( fd, FIONBIO , &noBlock );   if ( errNoBlock != 0 )   {      assert(0);   }#else   int flags  = fcntl( fd, F_GETFL, 0);   int errNoBlock = fcntl(fd, F_SETFL, flags | O_NONBLOCK );   if ( errNoBlock != 0 ) // !cj! I may have messed up this line    {      assert(0);   }#endif}int main(){#ifdef WIN32    WORD wVersionRequested = MAKEWORD( 2, 2 );   WSADATA wsaData;   int err;   err = WSAStartup( wVersionRequested, &wsaData );   if ( err != 0 )    {      // could not find a usable WinSock DLL      //cerr << "Could not load winsock" << endl;      assert(0); // is this is failing, try a different version that 2.2, 1.0 or later will likely work       exit(1);   }#endif   // contexts for each connection    SSL* ssl[MAX_CONNECTIONS];   // buffers for each connection   BIO* bio[MAX_CONNECTIONS];   // file descriptors for each connection   Socket fd[MAX_CONNECTIONS];   // ip address of other side of connection    int  peerip[MAX_CONNECTIONS];   // root cert list    X509_STORE* certAuthorities;   // my public cert   X509* publicCert;   // my private key    EVP_PKEY* privateKey;   // SSL Context    SSL_CTX* ctx;      Socket mFd;      char* password = "password";      for ( int i=0; i<MAX_CONNECTIONS; i++ )   {      fd[i]=-1;      bio[i]=0;      ssl[i]=0;   }      // load public cert    FILE* fp = fopen("id.pem","rb");   if ( !fp )   {      cerr << "Could not read public cert" <<endl; exit(1);   }   publicCert = PEM_read_X509(fp,NULL,NULL,NULL);   if (!publicCert)   {      cerr << "Error reading contents of public cert"<<endl; exit(1);   }   cerr << "Loaded public cert"<<endl;   // load private key    fp = fopen("id_key.pem","rb");   if ( !fp )   {      cerr << "Could not read private key"<<endl; exit(1);   }   privateKey = PEM_read_PrivateKey(fp,NULL,NULL,password);   if (!privateKey)   {      cerr << "Error reading contents of private key file "<<endl;exit(1);   }   cerr << "Loaded private key "<<endl;      // load root certs    certAuthorities = X509_STORE_new();   assert( certAuthorities );   if ( X509_STORE_load_locations(certAuthorities,"root.pem",NULL) != 1 )   {        cerr << "Error reading contents of root cert file "<<endl;   }   cerr << "Loaded public CAs"<<endl;      // set up main security context       SSL_library_init();      SSL_load_error_strings();      OpenSSL_add_all_ciphers();   OpenSSL_add_all_digests();      ERR_load_crypto_strings();      ctx=SSL_CTX_new( TLSv1_method() );   assert( ctx );      int ok;   ok = SSL_CTX_use_certificate(ctx, publicCert);   assert( ok == 1);      ok = SSL_CTX_use_PrivateKey(ctx,privateKey);   assert( ok == 1);      assert( certAuthorities );   SSL_CTX_set_cert_store(ctx, certAuthorities);         // open a socket to listen for requests on    mFd = socket(PF_INET, SOCK_STREAM, 0);   sockaddr_in addr;   addr.sin_family = AF_INET;   addr.sin_addr.s_addr = htonl(INADDR_ANY);    addr.sin_port = htons(STUN_PORT);      if ( bind( mFd, (struct sockaddr*) &addr, sizeof(addr)) == SOCKET_ERROR )   {      int err = errno;      if ( err == EADDRINUSE )      {         cerr << "Port already in use"<<endl;      }      else      {         cerr << "Could not bind to port"<<endl;      }            exit(0);   }   makeSocketNonBlocking(mFd);   int e = listen(mFd,64 );   if (e != 0 )   {      assert(0);   }   cerr << "Ready for requests" << endl;      while ( true )    {      // set up the read fd set for select       fd_set read;      FD_ZERO(&read);      int size=0;      FD_SET(mFd, &read);      size = mFd+1;      for ( int i=0; i<MAX_CONNECTIONS; i++ )      {         if ( fd[i] > 0 )         {            FD_SET(fd[i], &read);             size = ( int(fd[i]+1) > size) ? int(fd[i]+1) : size;         }               }      // do a select       unsigned long ms = 500;      struct timeval tv;      tv.tv_sec = (ms/1000);      tv.tv_usec = (ms%1000)*1000;      int e = select(size, &read, NULL, NULL, &tv);            cerr << "." ;            // process any new connections       if ( FD_ISSET(mFd, &read))      {         cerr << "Got a new connection" << endl;                  // find an unused connection          int i=0;         for ( ; i<MAX_CONNECTIONS; i++ )         {            if ( fd[i] == -1 )             {               break;            }         }                  if ( i >= MAX_CONNECTIONS )         {            cerr << "Ran out of connections to use "<<endl;            break;         }                  struct sockaddr_in peer;         int peerLen=sizeof(peer);         fd[i] = accept( mFd, (struct sockaddr*)&peer,(socklen_t*)&peerLen);         if ( fd[i] == -1 )         {            int err = errno;            cerr << "Error on accept: " << strerror(err)<<endl;            break;         }                  int* ptr =  (int*)( &peer.sin_addr );         peerip[i] = *ptr;                  ssl[i] = NULL;                  ssl[i] = SSL_new(ctx);         assert(ssl[i]);                  bio[i] = BIO_new_socket(fd[i],0/*close flag*/);         assert( bio[i] );                  SSL_set_bio( ssl[i], bio[i], bio[i] );                  int ok=0;         ok = SSL_accept(ssl[i]);                  if ( ok != 1 )         {            int err = SSL_get_error(ssl[i],ok);            char buf[256];            ERR_error_string_n(err,buf,sizeof(buf));                        cerr << "ssl connection failed "<<endl;                        bio[i] = NULL;         }                  makeSocketNonBlocking(fd[i]);      }            // process reads and writes       for (int i=0; i<MAX_CONNECTIONS; i++)       {         if ( ssl[i] )            if (  FD_ISSET( fd[i], &read) ||  SSL_pending(ssl[i])  )            {               cerr << "got a message on connection " << i << endl;                           char buf[STUN_MAX_MESSAGE_SIZE];                                  int ret = SSL_read(ssl[i],buf,sizeof(buf));               if (ret < 0 )               {                  int err = SSL_get_error(ssl[i],ret);                  switch (err)                  {                     case SSL_ERROR_WANT_READ:                     case SSL_ERROR_WANT_WRITE:                     case SSL_ERROR_NONE:                     {                        cerr << "Got TLS read got condition of " << err  <<endl;                     }                     break;                     default:                     {                        char buf[256];                        ERR_error_string_n(err,buf,sizeof(buf));                        cerr << "Got TLS read error " << err  << " " << buf  <<endl;                     }                     break;                  }                  // !cj! - big mem leak here - need to close and cleanup                   closesocket( fd[i] );                  fd[i] = -1;                  ssl[i]=0;               }                           cerr << "Received message with " << ret << " bytes"<<endl;                           StunAddress4 from;               StunAddress4 myAddr;               StunAddress4 altAddr;               StunMessage resp;               StunAddress4 destination;               StunAtrString hmacPassword;               bool changePort;               bool changeIp;                           from.addr = peerip[i];                           bool ok = stunServerProcessMsg( buf,ret,                                                from,                                                myAddr,                                               altAddr,                                                &resp,                                               &destination,                                               &hmacPassword,                                               &changePort,                                               &changeIp,                                               true /*verbose*/ );               if (!ok )               {                   cerr << "Message did not parse - closeing conneciton " << i  <<endl;                  closesocket( fd[i] );                  fd[i] = -1;                  ssl[i]=0;               }                           if (ok)               {                  int len = stunEncodeMessage( resp, buf, sizeof(buf), hmacPassword );                             ret = SSL_write(ssl[i],(const char*)buf,len);                  if (ret < 0 )                  {                     int err = SSL_get_error(ssl[i],ret);                     switch (err)                     {                        case SSL_ERROR_WANT_READ:                        case SSL_ERROR_WANT_WRITE:                        case SSL_ERROR_NONE:                        {                           cerr << "Got TLS write got codition of " << err  <<endl;                        }                        break;                        default:                        {                           cerr << "Got TLS write error " << err  <<endl;                        }                        break;                     }                     // !cj! big mem leak - need to cleanup                      closesocket( fd[i] );                     fd[i] = -1;                     ssl[i]=0;                  }               }            }      }   }      return 0;}/* ==================================================================== * The Vovida Software License, Version 1.0  *  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: *  * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. *  * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. *  * 3. The names "VOCAL", "Vovida Open Communication Application Library", *    and "Vovida Open Communication Application Library (VOCAL)" must *    not be used to endorse or promote products derived from this *    software without prior written permission. For written *    permission, please contact vocal@vovida.org. * * 4. Products derived from this software may not be called "VOCAL", nor *    may "VOCAL" appear in their name, without prior written *    permission of Vovida Networks, Inc. *  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. *  * ==================================================================== *  * This software consists of voluntary contributions made by Vovida * Networks, Inc. and many individuals on behalf of Vovida Networks, * Inc.  For more information on Vovida Networks, Inc., please see * <http://www.vovida.org/>. * */// Local Variables:// mode:c++// c-file-style:"ellemtel"// c-file-offsets:((case-label . +))// indent-tabs-mode:nil// End:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -