• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

SocksProxy.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 /*
00025   This implements SOCKS server. We intecept the http traffic and send it
00026   through HTTP. Others are tunneled through directly to the socks server.
00027 
00028 
00029 */
00030 #include "libts.h"
00031 #include "StatSystem.h"
00032 #include "P_Net.h"
00033 #include "I_OneWayTunnel.h"
00034 #include "HttpSessionAccept.h"
00035 
00036 enum
00037 {
00038   socksproxy_http_connections_stat,
00039   socksproxy_tunneled_connections_stat,
00040 
00041   socksproxy_stat_count
00042 };
00043 static RecRawStatBlock *socksproxy_stat_block;
00044 
00045 #define SOCKSPROXY_INC_STAT(x) \
00046         RecIncrRawStat(socksproxy_stat_block, mutex->thread_holding, x)
00047 
00048 struct SocksProxy: public Continuation
00049 {
00050   typedef int (SocksProxy::*EventHandler) (int event, void *data);
00051 
00052   enum
00053   { SOCKS_INIT = 1, SOCKS_ACCEPT, AUTH_DONE, SERVER_TUNNEL,
00054     HTTP_REQ, RESP_TO_CLIENT, ALL_DONE, SOCKS_ERROR
00055   };
00056 
00057     SocksProxy()
00058   : Continuation(),
00059     clientVC(0), clientVIO(0), buf(0), timeout(0),
00060     auth_handler(0), version(0), state(SOCKS_INIT), recursion(0), pending_action(NULL)
00061   {
00062   }
00063    ~SocksProxy()
00064   {
00065   }
00066 
00067 
00068   //int startEvent(int event, void * data);
00069   int mainEvent(int event, void *data);
00070   int setupHttpRequest(unsigned char *p);
00071   //int setupServerTunnel(unsigned char * p);
00072 
00073   int sendResp(bool granted);
00074 
00075   void init(NetVConnection * netVC);
00076   void free();
00077 
00078 private:
00079 
00080   NetVConnection * clientVC;
00081   VIO *clientVIO;
00082 
00083   MIOBuffer *buf;
00084   IOBufferReader *reader;
00085   Event *timeout;
00086 
00087   SocksAuthHandler auth_handler;
00088 
00089   unsigned char version;
00090 
00091   int state;
00092   int recursion;
00093   Action *pending_action;
00094 };
00095 
00096 ClassAllocator<SocksProxy> socksProxyAllocator("socksProxyAllocator");
00097 
00098 void
00099 SocksProxy::init(NetVConnection * netVC)
00100 {
00101   mutex = new_ProxyMutex();
00102   buf = new_MIOBuffer();
00103   reader = buf->alloc_reader();
00104 
00105   MUTEX_LOCK(lock, mutex, this_ethread());
00106 
00107   SET_HANDLER((EventHandler) & SocksProxy::mainEvent);
00108 
00109   mainEvent(NET_EVENT_ACCEPT, netVC);
00110 }
00111 
00112 void
00113 SocksProxy::free()
00114 {
00115   if (buf)
00116     free_MIOBuffer(buf);
00117 
00118   mutex = NULL;
00119 
00120   socksProxyAllocator.free(this);
00121 }
00122 
00123 int
00124 SocksProxy::mainEvent(int event, void *data)
00125 {
00126   int ret = EVENT_DONE;
00127   unsigned char *p;
00128 
00129   VIO *vio;
00130   int64_t n_read_avail;
00131   //int n_consume;
00132 
00133   recursion++;
00134 
00135   switch (event) {
00136 
00137   case NET_EVENT_ACCEPT:
00138     state = SOCKS_ACCEPT;
00139     Debug("SocksProxy", "Proxy got accept event\n");
00140 
00141     clientVC = (NetVConnection *) data;
00142     clientVC->socks_addr.reset();
00143     //Fall through:
00144   case VC_EVENT_WRITE_COMPLETE:
00145 
00146     switch (state) {
00147     case HTTP_REQ:{
00148       HttpSessionAccept::Options ha_opt;
00149       //This is a WRITE_COMPLETE. vio->nbytes == vio->ndone is true
00150 
00151       SOCKSPROXY_INC_STAT(socksproxy_http_connections_stat);
00152       Debug("SocksProxy", "Handing over the HTTP request\n");
00153 
00154       ha_opt.transport_type = clientVC->attributes;
00155       HttpSessionAccept http_accept(ha_opt);
00156       http_accept.mainEvent(NET_EVENT_ACCEPT, clientVC);
00157       state = ALL_DONE;
00158       break;
00159       }
00160 
00161     case RESP_TO_CLIENT:
00162       state = SOCKS_ERROR;
00163       break;
00164 
00165     default:
00166       buf->reset();
00167       timeout = this_ethread()
00168         ->schedule_in(this, HRTIME_SECONDS(netProcessor.socks_conf_stuff->socks_timeout));
00169       clientVC->do_io_read(this, INT64_MAX, buf);
00170     }
00171 
00172     break;
00173 
00174   case VC_EVENT_WRITE_READY:
00175     Debug("SocksProxy", "Received unexpected write_ready\n");
00176     break;
00177 
00178   case VC_EVENT_READ_COMPLETE:
00179     Debug("SocksProxy", "Oops! We should never get Read_Complete.\n");
00180     // FALLTHROUGH
00181   case VC_EVENT_READ_READY:{
00182       unsigned char *port_ptr = 0;
00183 
00184       ret = EVENT_CONT;
00185       vio = (VIO *) data;
00186 
00187       n_read_avail = reader->block_read_avail();
00188       ink_assert(n_read_avail == reader->read_avail());
00189       p = (unsigned char *) reader->start();
00190 
00191       if (n_read_avail >= 2) {
00192 
00193         Debug(state == SOCKS_ACCEPT ? "SocksProxy" : "", "Accepted connection from a version %d client\n", (int) p[0]);
00194 
00195         //Most of the time request is just a single packet
00196         switch (p[0]) {
00197 
00198         case SOCKS4_VERSION:
00199           ink_assert(state == SOCKS_ACCEPT);
00200 
00201           if (n_read_avail > 8) {
00202             //read the user name
00203             int i = 8;
00204             while (p[i] != 0 && n_read_avail > i)
00205               i++;
00206 
00207             if (p[i] == 0) {
00208               port_ptr = &p[2];
00209               clientVC->socks_addr.type = SOCKS_ATYPE_IPV4;
00210               reader->consume(i + 1);
00211               //n_consume = i+1;
00212               ret = EVENT_DONE;
00213             }
00214           }
00215           break;
00216 
00217         case SOCKS5_VERSION:
00218 
00219           if (state == SOCKS_ACCEPT) {
00220             if (n_read_avail >= 2 + p[1]) {
00221               auth_handler = &socks5ServerAuthHandler;
00222               ret = EVENT_DONE;
00223             }
00224           } else {
00225             ink_assert(state == AUTH_DONE);
00226 
00227             if (n_read_avail >= 5) {
00228               int req_len;
00229 
00230               switch (p[3]) {
00231               case SOCKS_ATYPE_IPV4:
00232                 req_len = 10;
00233                 break;
00234               case SOCKS_ATYPE_FQHN:
00235                 req_len = 7 + p[4];
00236                 break;
00237               case SOCKS_ATYPE_IPV6:
00238                 req_len = 22;
00239                 break;
00240               default:
00241                 req_len = INT_MAX;
00242                 Debug("SocksProxy", "Illegal address type(%d)\n", (int) p[3]);
00243               }
00244 
00245               if (n_read_avail >= req_len) {
00246                 port_ptr = &p[req_len - 2];
00247                 clientVC->socks_addr.type = p[3];
00248                 auth_handler = NULL;
00249                 reader->consume(req_len);
00250                 ret = EVENT_DONE;
00251               }
00252             }
00253           }
00254           break;
00255 
00256         default:
00257           Warning("Wrong version for Socks: %d\n", p[0]);
00258           state = SOCKS_ERROR;
00259         }
00260       }
00261 
00262       if (ret == EVENT_DONE) {
00263         timeout->cancel(this);
00264         timeout = 0;
00265 
00266         if (auth_handler) {
00267 
00268           /* disable further reads */
00269           vio->nbytes = vio->ndone;
00270 
00271           //There is some auth stuff left.
00272           if (invokeSocksAuthHandler(auth_handler, SOCKS_AUTH_READ_COMPLETE, p) >= 0) {
00273             buf->reset();
00274             p = (unsigned char *) buf->start();
00275 
00276             int n_bytes = invokeSocksAuthHandler(auth_handler,
00277                                                  SOCKS_AUTH_FILL_WRITE_BUF, p);
00278             ink_assert(n_bytes > 0);
00279 
00280             buf->fill(n_bytes);
00281 
00282             clientVC->do_io_write(this, n_bytes, reader, 0);
00283 
00284             state = AUTH_DONE;
00285           } else {
00286             Debug("SocksProxy", "Auth_handler returned error\n");
00287             state = SOCKS_ERROR;
00288           }
00289 
00290         } else {
00291           int port = port_ptr[0] * 256 + port_ptr[1];
00292           version = p[0];
00293 
00294           if (port == netProcessor.socks_conf_stuff->http_port && p[1] == SOCKS_CONNECT) {
00295 
00296             /* disable further reads */
00297             vio->nbytes = vio->ndone;
00298 
00299             ret = setupHttpRequest(p);
00300             sendResp(true);
00301             state = HTTP_REQ;
00302 
00303           } else {
00304             SOCKSPROXY_INC_STAT(socksproxy_tunneled_connections_stat);
00305             Debug("SocksProxy", "Tunnelling the connection for port %d", port);
00306 
00307             if (clientVC->socks_addr.type != SOCKS_ATYPE_IPV4) {
00308               //We dont support other kinds of addresses for tunnelling
00309               //if this is a hostname we could do host look up here
00310               mainEvent(NET_EVENT_OPEN_FAILED, NULL);
00311               break;
00312             }
00313 
00314             uint32_t ip;
00315             struct sockaddr_in addr;
00316 
00317             memcpy(&ip, &p[4], 4);
00318             ats_ip4_set(&addr, ip, htons(port));
00319 
00320             state = SERVER_TUNNEL;
00321             clientVIO = vio;    // used in the tunnel
00322 
00323             //tunnel the connection.
00324 
00325             NetVCOptions vc_options;
00326             vc_options.socks_support = p[1];
00327             vc_options.socks_version = version;
00328 
00329             Action *action = netProcessor.connect_re(this, ats_ip_sa_cast(&addr), &vc_options);
00330             if (action != ACTION_RESULT_DONE) {
00331               ink_assert(pending_action == NULL);
00332               pending_action = action;
00333             }
00334           }
00335         }
00336       }                         //if (ret == EVENT_DONE)
00337 
00338       break;
00339     }
00340 
00341   case NET_EVENT_OPEN:{
00342       pending_action = NULL;
00343       ink_assert(state == SERVER_TUNNEL);
00344       Debug("SocksProxy", "open to Socks server succeeded\n");
00345 
00346       NetVConnection *serverVC;
00347       serverVC = (NetVConnection *) data;
00348 
00349       OneWayTunnel *c_to_s = OneWayTunnel::OneWayTunnel_alloc();
00350       OneWayTunnel *s_to_c = OneWayTunnel::OneWayTunnel_alloc();
00351 
00352       c_to_s->init(clientVC, serverVC, NULL, clientVIO, reader);
00353       s_to_c->init(serverVC, clientVC, /*aCont = */ NULL, 0 /*best guess */ ,
00354                    c_to_s->mutex);
00355 
00356       OneWayTunnel::SetupTwoWayTunnel(c_to_s, s_to_c);
00357 
00358       buf = 0;                  // do not free buf. Tunnel will do that.
00359       state = ALL_DONE;
00360       break;
00361     }
00362 
00363   case NET_EVENT_OPEN_FAILED:
00364     pending_action = NULL;
00365     sendResp(false);
00366     state = RESP_TO_CLIENT;
00367     Debug("SocksProxy", "open to Socks server failed\n");
00368     break;
00369 
00370   case EVENT_INTERVAL:
00371     timeout = 0;
00372     Debug("SocksProxy", "SocksProxy timeout, state = %d\n", state);
00373     state = SOCKS_ERROR;
00374     break;
00375 
00376   case VC_EVENT_ERROR:
00377   case VC_EVENT_INACTIVITY_TIMEOUT:
00378   case VC_EVENT_ACTIVE_TIMEOUT:
00379   case VC_EVENT_EOS:
00380     Debug("SocksProxy", "VC_EVENT (state: %d error: %s)\n", state, get_vc_event_name(event));
00381     state = SOCKS_ERROR;
00382     break;
00383 
00384   default:
00385     ink_assert(!"bad case value\n");
00386     state = SOCKS_ERROR;
00387   }
00388 
00389   if (state == SOCKS_ERROR) {
00390     if (pending_action)
00391       pending_action->cancel();
00392 
00393     if (timeout)
00394       timeout->cancel(this);
00395 
00396     if (clientVC) {
00397       Debug("SocksProxy", "Closing clientVC on error\n");
00398       clientVC->do_io_close();
00399       clientVC = NULL;
00400     }
00401 
00402     state = ALL_DONE;
00403   }
00404 
00405   recursion--;
00406 
00407   if (state == ALL_DONE && recursion == 0) {
00408     free();
00409   }
00410 
00411   return ret;
00412 }
00413 
00414 int
00415 SocksProxy::sendResp(bool granted)
00416 {
00417   int n_bytes;
00418 
00419   // In SOCKS 4, IP addr and Dest Port fields are ignored.
00420   // In SOCKS 5, IP addr and Dest Port are the ones we use to connect to the
00421   // real host. In our case, it does not make sense, since we may not
00422   // connect at all. Set these feilds to zeros. Any socks client which uses
00423   // these breaks caching.
00424 
00425 
00426   buf->reset();
00427   unsigned char *p = (unsigned char *) buf->start();
00428 
00429   if (version == SOCKS4_VERSION) {
00430     p[0] = 0;
00431     p[1] = (granted) ? SOCKS4_REQ_GRANTED : SOCKS4_CONN_FAILED;
00432     n_bytes = 8;
00433   } else {
00434     p[0] = SOCKS5_VERSION;
00435     p[1] = (granted) ? SOCKS5_REQ_GRANTED : SOCKS5_CONN_FAILED;
00436     p[2] = 0;
00437     p[3] = SOCKS_ATYPE_IPV4;
00438     p[4] = p[5] = p[6] = p[7] = p[8] = p[9] = 0;
00439     n_bytes = 10;
00440   }
00441 
00442   buf->fill(n_bytes);
00443   clientVC->do_io_write(this, n_bytes, reader, 0);
00444 
00445   return n_bytes;
00446 }
00447 
00448 
00449 int
00450 SocksProxy::setupHttpRequest(unsigned char *p)
00451 {
00452   int ret = EVENT_DONE;
00453 
00454   SocksAddrType *a = &clientVC->socks_addr;
00455 
00456   //read the ip addr buf
00457   //In both SOCKS4 and SOCKS5 addr starts after 4 octets
00458   switch (a->type) {
00459 
00460   case SOCKS_ATYPE_IPV4:
00461     a->addr.ipv4[0] = p[4];
00462     a->addr.ipv4[1] = p[5];
00463     a->addr.ipv4[2] = p[6];
00464     a->addr.ipv4[3] = p[7];
00465     break;
00466 
00467   case SOCKS_ATYPE_FQHN:
00468     //This is stored as a zero terminicated string
00469     a->addr.buf = (unsigned char *)ats_malloc(p[4] + 1);
00470     memcpy(a->addr.buf, &p[5], p[4]);
00471     a->addr.buf[p[4]] = 0;
00472     break;
00473   case SOCKS_ATYPE_IPV6:
00474     //a->addr.buf = (unsigned char *)ats_malloc(16);
00475     //memcpy(a->addr.buf, &p[4], 16);
00476     //dont think we will use "proper" IPv6 addr anytime soon.
00477     //just use the last 4 octets as IPv4 addr:
00478     a->type = SOCKS_ATYPE_IPV4;
00479     a->addr.ipv4[0] = p[16];
00480     a->addr.ipv4[0] = p[17];
00481     a->addr.ipv4[0] = p[18];
00482     a->addr.ipv4[0] = p[19];
00483 
00484     break;
00485   default:
00486     ink_assert(!"bad case value");
00487   }
00488 
00489   return ret;
00490 }
00491 
00492 
00493 
00494 
00495 static void
00496 new_SocksProxy(NetVConnection * netVC)
00497 {
00498   SocksProxy *proxy = socksProxyAllocator.alloc();
00499   proxy->init(netVC);
00500 }
00501 
00502 struct SocksAccepter: public Continuation
00503 {
00504 
00505   typedef int (SocksAccepter::*SocksAccepterHandler) (int, void *);
00506 
00507   int mainEvent(int event, NetVConnection * netVC)
00508   {
00509 
00510     ink_assert(event == NET_EVENT_ACCEPT);
00511     //Debug("Socks", "Accepter got ACCEPT event\n");
00512 
00513     new_SocksProxy(netVC);
00514 
00515     return EVENT_CONT;
00516   }
00517 
00518   //There is no state used we dont need a mutex
00519   SocksAccepter():Continuation(NULL)
00520   {
00521     SET_HANDLER((SocksAccepterHandler) & SocksAccepter::mainEvent);
00522   }
00523 };
00524 
00525 void
00526 start_SocksProxy(int port)
00527 {
00528   Debug("SocksProxy", "Accepting SocksProxy connections on port %d\n", port);
00529   NetProcessor::AcceptOptions opt;
00530   opt.local_port = port;
00531   netProcessor.main_accept(new SocksAccepter(), NO_FD, opt);
00532 
00533   socksproxy_stat_block = RecAllocateRawStatBlock(socksproxy_stat_count);
00534 
00535   if (socksproxy_stat_block) {
00536     RecRegisterRawStat(socksproxy_stat_block, RECT_PROCESS,
00537                        "proxy.process.socks.proxy.http_connections",
00538                        RECD_INT, RECP_PERSISTENT, socksproxy_http_connections_stat, RecRawStatSyncCount);
00539 
00540     RecRegisterRawStat(socksproxy_stat_block, RECT_PROCESS,
00541                        "proxy.process.socks.proxy.tunneled_connections",
00542                        RECD_INT, RECP_PERSISTENT, socksproxy_tunneled_connections_stat, RecRawStatSyncCount);
00543   }
00544 }
00545 
00546 int
00547 socks5ServerAuthHandler(int event, unsigned char *p, void (**h_ptr) (void))
00548 {
00549 
00550   int ret = 0;
00551   //bool no_auth_needed=true;
00552 
00553   switch (event) {
00554 
00555   case SOCKS_AUTH_READ_COMPLETE:
00556 
00557     ink_assert(p[0] == SOCKS5_VERSION);
00558     Debug("SocksProxy", "Socks read initial auth info\n");
00559     //do nothing
00560     break;
00561 
00562   case SOCKS_AUTH_FILL_WRITE_BUF:
00563     Debug("SocksProxy", "No authentication is required\n");
00564     p[0] = SOCKS5_VERSION;
00565     p[1] = 0;                   //no authentication necessary
00566     ret = 2;
00567     // FALLTHROUGH
00568   case SOCKS_AUTH_WRITE_COMPLETE:
00569     //nothing to do
00570     *h_ptr = NULL;
00571     break;
00572 
00573   default:
00574     ink_assert(!"bad case value");
00575     ret = -1;
00576   }
00577 
00578   return ret;
00579 }

Generated by  doxygen 1.7.1