void SocksConnection::HandleRequest() { if(_socket->bytesAvailable() < _addr_len) { return; } QByteArray socks_addr = _socket->read(_addr_len); QString host; quint16 port; if(!ParseSocksAddress(socks_addr, host, port)) { EstablishFail(SocksReply_AddressTypeNotSupported); return; } qDebug() << "SOCKS Host Parsed:" << host << port; switch(_command) { case SocksCommand_Connect: StartConnect(host, port); break; case SocksCommand_UdpAssociate: StartUdpAssociate(host, port); break; default: qDebug() << "FAIL: Command not supported"; EstablishFail(SocksReply_CommandNotSupported); return; } if(_socket->bytesAvailable()) { ReadFromSocket(); } }
void SocksConnection::ProcessRequest() { if(_addr_buf.count() < 3) { qDebug() << "Address string is too short"; return EstablishFail(SocksReply_AddressTypeNotSupported); } int bytes_read; SocksHostAddress dest_addr; SocksAddressType code = ParseSocksAddressBytes(_addr_type, _addr_buf, dest_addr, bytes_read); if(!(code == SocksAddress_IPv4 || code == SocksAddress_DomainName)) { qDebug() << "SOCKS FAIL!"; return EstablishFail(SocksReply_AddressTypeNotSupported); } qDebug() << "SOCKS Parsed Host" << dest_addr.ToString(); switch(_command) { case SocksCommand_Connect: StartConnect(dest_addr); return; case SocksCommand_UdpAssociate: StartUdpAssociate(dest_addr); return; default: qDebug() << "FAIL: Command not supported"; return EstablishFail(SocksReply_CommandNotSupported); } }
void SocksConnection::StartUdpAssociate(const QString &, quint16) { _udp_socket = QSharedPointer<QUdpSocket>(new QUdpSocket()); if(!_udp_socket->bind(_socket->localAddress(), 0)) { EstablishFail(SocksReply_GeneralServerFailure); return; } connect(_udp_socket.data(), SIGNAL(readyRead()), this, SLOT(UdpReadFromSocket())); connect(_udp_socket.data(), SIGNAL(disconnected()), this, SLOT(Close())); connect(_udp_socket.data(), SIGNAL(error(QAbstractSocket::SocketError)), SLOT(UdpHandleError(QAbstractSocket::SocketError))); QByteArray verif_bytes = _verif_key->GetByteArray(); _conn_id = Hash().ComputeHash(verif_bytes); emit ProxyConnected(); _state = ConnState_Connected; TunnelPacket packet = TunnelPacket::BuildUdpStart(GetConnectionId(), verif_bytes); SendUpstreamPacket(packet.GetPacket()); qDebug() << "SOCKS UDP Addr" << _udp_socket->localAddress() << _udp_socket->localPort(); WriteSocksReply(SocksReply_Succeeded, _udp_socket->localAddress(), _udp_socket->localPort()); }
void SocksConnection::HandleRequestHeader() { int header_len = 5; if(_socket->bytesAvailable() < header_len) { return; } QByteArray request_buf = _socket->read(3); char addr[2]; Q_ASSERT(2 == _socket->peek(addr, 2)); // Request header -- 4 bytes fixed: // byte[0] = version // byte[1] = command (connect, bind, or UDP associate) // byte[2] = reserved // byte[3] = address type // byte[4] = first byte of address if(((uchar)request_buf[0] != (uchar)SocksVersion_5) || request_buf[2]) { Close(); return; } _command = request_buf[1]; _addr_len = 1; switch(addr[0]) { case SocksAddress_IPv4: qDebug() << "IS IPv4 address"; _addr_len += 4; break; case SocksAddress_DomainName: qDebug() << "IS DomainName address"; _addr_len += addr[1] + 1; break; case SocksAddress_IPv6: _addr_len += 16; break; default: qDebug() << "Received an invalid SocksAddress type"; EstablishFail(SocksReply_AddressTypeNotSupported); return; } // Add two bytes for the port number _addr_len += 2; _state = ConnState_WaitingForRequest; if(_socket->bytesAvailable() >= _addr_len) { ReadFromSocket(); } }
void SocksConnection::StartUdpAssociate(const SocksHostAddress &peer_host) { if(!peer_host.IsHostName() && peer_host.GetPort() && peer_host.GetAddress() != QHostAddress::Any && peer_host.GetAddress() != QHostAddress::AnyIPv6) { _udp_peer = peer_host.GetAddress(); _udp_peer_port = peer_host.GetPort(); } _udp_socket = QSharedPointer<QUdpSocket>(new QUdpSocket()); // Bind to some accessible port on the same address as the // SOCKS TCP server _udp_socket->bind(_socket->localAddress(), 0); if(_udp_socket->state() != QAbstractSocket::BoundState) { return EstablishFail(SocksReply_GeneralServerFailure); } // Connect to methods here connect(_udp_socket.data(), SIGNAL(readyRead()), this, SLOT(UdpReadFromSocket())); connect(_udp_socket.data(), SIGNAL(disconnected()), this, SLOT(Close())); connect(_udp_socket.data(), SIGNAL(error(QAbstractSocket::SocketError)), SLOT(UdpHandleError(QAbstractSocket::SocketError))); QByteArray verif_bytes = _verif_key->GetByteArray(); QByteArray packet = UdpStartPacket(verif_bytes).ToByteArray(); // Start the connection _conn_id = _hash_algo->ComputeHash(verif_bytes); emit ProxyConnected(); _state = ConnState_Connected; SendUpstreamPacket(packet); qDebug() << "SOCKS UDP Addr" << _udp_socket->localAddress() << _udp_socket->localPort(); SocksConnection::WriteSocksReply(SocksReply_Succeeded, _udp_socket->localAddress(), _udp_socket->localPort()); }