2
* socks.cpp - SOCKS5 TCP proxy client/server
3
* Copyright (C) 2003 Justin Karneges
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
#include <QHostAddress>
24
#include <QStringList>
27
#include <QSocketNotifier>
31
#include <sys/types.h>
32
#include <netinet/in.h>
55
//----------------------------------------------------------------------------
57
//----------------------------------------------------------------------------
59
class SocksUDP::Private
64
QHostAddress routeAddr;
70
SocksUDP::SocksUDP(SocksClient *sc, const QString &host, int port, const QHostAddress &routeAddr, int routePort)
75
d->sd = new QUdpSocket(this);
76
connect(d->sd, SIGNAL(readyRead()), SLOT(sd_readyRead()));
79
d->routeAddr = routeAddr;
80
d->routePort = routePort;
89
void SocksUDP::change(const QString &host, int port)
95
void SocksUDP::write(const QByteArray &data)
97
d->sd->writeDatagram(data.data(), data.size(), d->routeAddr, d->routePort);
100
void SocksUDP::sd_activated()
102
while (d->sd->hasPendingDatagrams()) {
104
datagram.resize(d->sd->pendingDatagramSize());
105
d->sd->readDatagram(datagram.data(), datagram.size());
106
packetReady(datagram);
110
//----------------------------------------------------------------------------
112
//----------------------------------------------------------------------------
113
#define REQ_CONNECT 0x01
114
#define REQ_BIND 0x02
115
#define REQ_UDPASSOCIATE 0x03
117
#define RET_SUCCESS 0x00
118
#define RET_UNREACHABLE 0x04
119
#define RET_CONNREFUSED 0x05
121
// spc = socks packet client
122
// sps = socks packet server
123
// SPCS = socks packet client struct
124
// SPSS = socks packet server struct
127
static QByteArray spc_set_version(bool hasCreds)
130
ver.resize(hasCreds? 4 : 3);
131
ver[0] = 0x05; // socks version 5
132
ver[2] = 0x00; // no-auth
134
ver[1] = 0x02; // number of methods
135
ver[3] = 0x02; // username
137
ver[1] = 0x01; // number of methods
142
static QByteArray sps_set_version(int method)
153
unsigned char version;
154
QByteArray methodList;
157
static int spc_get_version(QByteArray &from, SPCS_VERSION *s)
161
if(from.at(0) != 0x05) // only SOCKS5 supported
165
unsigned char mlen = from.at(1);
167
if(num > 16) // who the heck has over 16 auth methods??
169
if(from.size() < 2 + num)
171
QByteArray a = ByteStream::takeArray(from, 2+num);
173
s->methodList.resize(num);
174
memcpy(s->methodList.data(), a.data() + 2, num);
180
unsigned char version;
181
unsigned char method;
184
static int sps_get_version(QByteArray &from, SPSS_VERSION *s)
188
QByteArray a = ByteStream::takeArray(from, 2);
195
static QByteArray spc_set_authUsername(const QByteArray &user, const QByteArray &pass)
197
int len1 = user.length();
198
int len2 = pass.length();
204
a.resize(1+1+len1+1+len2);
205
a[0] = 0x01; // username auth version 1
207
memcpy(a.data() + 2, user.data(), len1);
209
memcpy(a.data() + 3 + len1, pass.data(), len2);
213
static QByteArray sps_set_authUsername(bool success)
218
a[1] = success ? 0x00 : 0xff;
222
struct SPCS_AUTHUSERNAME
227
static int spc_get_authUsername(QByteArray &from, SPCS_AUTHUSERNAME *s)
231
unsigned char ver = from.at(0);
236
unsigned char ulen = from.at(1);
237
if((int)from.size() < ulen + 3)
239
unsigned char plen = from.at(ulen+2);
240
if((int)from.size() < ulen + plen + 3)
242
QByteArray a = ByteStream::takeArray(from, ulen + plen + 3);
244
QByteArray user, pass;
247
memcpy(user.data(), a.data()+2, ulen);
248
memcpy(pass.data(), a.data()+ulen+3, plen);
249
s->user = QString::fromUtf8(user);
250
s->pass = QString::fromUtf8(pass);
254
struct SPSS_AUTHUSERNAME
256
unsigned char version;
260
static int sps_get_authUsername(QByteArray &from, SPSS_AUTHUSERNAME *s)
264
QByteArray a = ByteStream::takeArray(from, 2);
266
s->success = ((char) a[1] == 0 ? true: false);
271
static QByteArray sp_set_request(const QHostAddress &addr, unsigned short port, unsigned char cmd1)
276
a[at++] = 0x05; // socks version 5
278
a[at++] = 0x00; // reserved
279
if(addr.protocol() == QAbstractSocket::IPv4Protocol || addr.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) {
280
a[at++] = 0x01; // address type = ipv4
281
quint32 ip4 = htonl(addr.toIPv4Address());
283
memcpy(a.data() + at, &ip4, 4);
288
Q_IPV6ADDR ip6 = addr.toIPv6Address();
290
for(int i = 0; i < 16; ++i)
296
quint16 p = htons(port);
297
memcpy(a.data() + at, &p, 2);
302
static QByteArray sp_set_request(const QString &host, quint16 port, unsigned char cmd1)
304
// detect for IP addresses
306
if(addr.setAddress(host))
307
return sp_set_request(addr, port, cmd1);
309
QByteArray h = host.toUtf8();
311
h = QString::fromUtf8(h).toUtf8(); // delete any partial characters?
312
int hlen = h.length();
317
a[at++] = 0x05; // socks version 5
319
a[at++] = 0x00; // reserved
320
a[at++] = 0x03; // address type = domain
325
memcpy(a.data() + at, h.data(), hlen);
330
unsigned short p = htons(port);
331
memcpy(a.data() + at, &p, 2);
338
unsigned char version;
346
static int sp_get_request(QByteArray &from, SPS_CONNREQ *s)
349
if((int)from.size() < full_len)
354
unsigned char atype = from.at(3);
358
if((int)from.size() < full_len)
361
memcpy(&ip4, from.data() + 4, 4);
362
addr.setAddress(ntohl(ip4));
364
else if(atype == 0x03) {
366
if((int)from.size() < full_len)
368
unsigned char host_len = from.at(4);
369
full_len += host_len;
370
if((int)from.size() < full_len)
374
memcpy(cs.data(), from.data() + 5, host_len);
375
host = QString::fromLatin1(cs);
377
else if(atype == 0x04) {
379
if((int)from.size() < full_len)
382
memcpy(a6, from.data() + 4, 16);
387
if((int)from.size() < full_len)
390
QByteArray a = ByteStream::takeArray(from, full_len);
393
memcpy(&p, a.data() + full_len - 2, 2);
397
s->address_type = atype;
405
enum { StepVersion, StepAuth, StepRequest };
407
class SocksClient::Private
410
Private(SocksClient *_q) :
425
bool incoming, waiting;
437
SocksClient::SocksClient(QObject *parent)
445
SocksClient::SocksClient(int s, QObject *parent)
452
d->sock.setSocket(s);
455
void SocksClient::init()
457
d = new Private(this);
458
connect(&d->sock, SIGNAL(connected()), SLOT(sock_connected()));
459
connect(&d->sock, SIGNAL(connectionClosed()), SLOT(sock_connectionClosed()));
460
connect(&d->sock, SIGNAL(delayedCloseFinished()), SLOT(sock_delayedCloseFinished()));
461
connect(&d->sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
462
connect(&d->sock, SIGNAL(bytesWritten(qint64)), SLOT(sock_bytesWritten(qint64)));
463
connect(&d->sock, SIGNAL(error(int)), SLOT(sock_error(int)));
465
resetConnection(true);
468
SocksClient::~SocksClient()
470
resetConnection(true);
474
QAbstractSocket* SocksClient::abstractSocket() const
476
return d->sock.abstractSocket();
479
void SocksClient::resetConnection(bool clear)
481
if(d->sock.state() != BSocket::Idle)
485
d->recvBuf.resize(0);
489
if (bytesAvailable()) {
490
setOpenMode(QIODevice::ReadOnly);
492
setOpenMode(QIODevice::NotOpen);
496
bool SocksClient::isIncoming() const
501
void SocksClient::setAuth(const QString &user, const QString &pass)
507
void SocksClient::connectToHost(const QString &proxyHost, int proxyPort, const QString &host, int port, bool udpMode)
509
resetConnection(true);
518
fprintf(stderr, "SocksClient: Connecting to %s:%d", qPrintable(proxyHost), proxyPort);
519
if(d->user.isEmpty())
520
fprintf(stderr, "\n");
522
fprintf(stderr, ", auth {%s,%s}\n", qPrintable(d->user), qPrintable(d->pass));
524
d->sock.connectToHost(d->host, d->port);
527
void SocksClient::close()
530
if(d->sock.bytesToWrite() == 0)
534
void SocksClient::writeData(const QByteArray &buf)
538
fprintf(stderr, "SocksClient: client write { ");
539
for(int n = 0; n < (int)buf.size(); ++n)
540
fprintf(stderr, "%02X ", (unsigned char)buf[n]);
541
fprintf(stderr, " } \n");
543
d->pending += buf.size();
547
qint64 SocksClient::writeData(const char *data, qint64 maxSize)
549
if(isOpen() && !d->udp)
550
return d->sock.write(data, maxSize);
554
qint64 SocksClient::readData(char *data, qint64 maxSize)
556
qint64 ret = ByteStream::readData(data, maxSize);
557
if (d->sock.state() != BSocket::Connected && !bytesAvailable()) {
558
setOpenMode(QIODevice::NotOpen);
563
qint64 SocksClient::bytesAvailable() const
565
return ByteStream::bytesAvailable();
568
qint64 SocksClient::bytesToWrite() const
571
return d->sock.bytesToWrite();
576
void SocksClient::sock_connected()
579
fprintf(stderr, "SocksClient: Connected\n");
582
d->step = StepVersion;
583
writeData(spc_set_version(!d->user.isEmpty())); // fixme requirement for auth should set outside
586
void SocksClient::sock_connectionClosed()
590
emit connectionClosed();
593
setError(ErrProxyNeg);
597
void SocksClient::sock_delayedCloseFinished()
601
delayedCloseFinished();
605
void SocksClient::sock_readyRead()
607
QByteArray block = d->sock.readAll();
609
//qDebug() << this << "::sock_readyRead " << block.size() << " bytes." <<
610
// "udp=" << d->udp << openMode();
613
processIncoming(block);
615
processOutgoing(block);
625
void SocksClient::processOutgoing(const QByteArray &block)
629
fprintf(stderr, "SocksClient: client recv { ");
630
for(int n = 0; n < (int)block.size(); ++n)
631
fprintf(stderr, "%02X ", (unsigned char)block[n]);
632
fprintf(stderr, " } \n");
636
if(d->step == StepVersion) {
638
int r = sps_get_version(d->recvBuf, &s);
640
resetConnection(true);
641
setError(ErrProxyNeg);
645
if(s.version != 0x05 || s.method == 0xff) {
647
fprintf(stderr, "SocksClient: Method selection failed\n");
649
resetConnection(true);
650
setError(ErrProxyNeg);
655
if(s.method == 0x00) {
657
d->authMethod = AuthNone;
659
else if(s.method == 0x02) {
660
str = "Username/Password";
661
d->authMethod = AuthUsername;
665
fprintf(stderr, "SocksClient: Server wants to use unknown method '%02x'\n", s.method);
667
resetConnection(true);
668
setError(ErrProxyNeg);
672
if(d->authMethod == AuthNone) {
673
// no auth, go straight to the request
676
else if(d->authMethod == AuthUsername) {
679
fprintf(stderr, "SocksClient: Authenticating [Username] ...\n");
681
writeData(spc_set_authUsername(d->user.toLatin1(), d->pass.toLatin1()));
685
if(d->step == StepAuth) {
686
if(d->authMethod == AuthUsername) {
688
int r = sps_get_authUsername(d->recvBuf, &s);
690
resetConnection(true);
691
setError(ErrProxyNeg);
695
if(s.version != 0x01) {
696
resetConnection(true);
697
setError(ErrProxyNeg);
701
resetConnection(true);
702
setError(ErrProxyAuth);
710
else if(d->step == StepRequest) {
712
int r = sp_get_request(d->recvBuf, &s);
714
resetConnection(true);
715
setError(ErrProxyNeg);
719
if(s.cmd != RET_SUCCESS) {
721
fprintf(stderr, "SocksClient: client << Error >> [%02x]\n", s.cmd);
723
resetConnection(true);
724
if(s.cmd == RET_UNREACHABLE)
725
setError(ErrHostNotFound);
726
else if(s.cmd == RET_CONNREFUSED)
727
setError(ErrConnectionRefused);
729
setError(ErrProxyNeg);
734
fprintf(stderr, "SocksClient: client << Success >>\n");
737
if(s.address_type == 0x03)
740
d->udpAddr = s.addr.toString();
744
setOpenMode(QIODevice::ReadWrite);
746
QPointer<QObject> self = this;
747
setOpenMode(QIODevice::ReadWrite);
752
if(!d->recvBuf.isEmpty()) {
753
appendRead(d->recvBuf);
754
d->recvBuf.resize(0);
761
void SocksClient::do_request()
764
fprintf(stderr, "SocksClient: Requesting ...\n");
766
d->step = StepRequest;
767
int cmd = d->udp ? REQ_UDPASSOCIATE : REQ_CONNECT;
769
if(!d->real_host.isEmpty())
770
buf = sp_set_request(d->real_host, d->real_port, cmd);
772
buf = sp_set_request(QHostAddress(), 0, cmd);
776
void SocksClient::sock_bytesWritten(qint64 x)
779
if(d->pending >= bytes) {
791
void SocksClient::sock_error(int x)
798
resetConnection(true);
799
if(x == BSocket::ErrHostNotFound)
800
setError(ErrProxyConnect);
801
else if(x == BSocket::ErrConnectionRefused)
802
setError(ErrProxyConnect);
803
else if(x == BSocket::ErrRead)
804
setError(ErrProxyNeg);
808
void SocksClient::serve()
811
d->step = StepVersion;
815
void SocksClient::processIncoming(const QByteArray &block)
819
fprintf(stderr, "SocksClient: server recv { ");
820
for(int n = 0; n < (int)block.size(); ++n)
821
fprintf(stderr, "%02X ", (unsigned char)block[n]);
822
fprintf(stderr, " } \n");
830
void SocksClient::continueIncoming()
832
if(d->recvBuf.isEmpty())
835
if(d->step == StepVersion) {
837
int r = spc_get_version(d->recvBuf, &s);
839
resetConnection(true);
840
setError(ErrProxyNeg);
844
if(s.version != 0x05) {
845
resetConnection(true);
846
setError(ErrProxyNeg);
851
for(int n = 0; n < (int)s.methodList.size(); ++n) {
852
unsigned char c = s.methodList[n];
856
methods |= AuthUsername;
859
emit incomingMethods(methods);
862
else if(d->step == StepAuth) {
864
int r = spc_get_authUsername(d->recvBuf, &s);
866
resetConnection(true);
867
setError(ErrProxyNeg);
872
incomingAuth(s.user, s.pass);
875
else if(d->step == StepRequest) {
877
int r = sp_get_request(d->recvBuf, &s);
879
resetConnection(true);
880
setError(ErrProxyNeg);
885
if(s.cmd == REQ_CONNECT) {
886
if(!s.host.isEmpty())
889
d->rhost = s.addr.toString();
891
incomingConnectRequest(d->rhost, d->rport);
893
else if(s.cmd == REQ_UDPASSOCIATE) {
894
incomingUDPAssociateRequest();
904
void SocksClient::chooseMethod(int method)
906
if(d->step != StepVersion || !d->waiting)
910
if(method == AuthNone) {
911
d->step = StepRequest;
921
writeData(sps_set_version(c));
925
void SocksClient::authGrant(bool b)
927
if(d->step != StepAuth || !d->waiting)
931
d->step = StepRequest;
935
writeData(sps_set_authUsername(b));
937
resetConnection(true);
943
void SocksClient::requestDeny()
945
if(d->step != StepRequest || !d->waiting)
950
writeData(sp_set_request(d->rhost, d->rport, RET_UNREACHABLE));
951
resetConnection(true);
954
void SocksClient::grantConnect()
956
if(d->step != StepRequest || !d->waiting)
961
writeData(sp_set_request(d->rhost, d->rport, RET_SUCCESS));
962
setOpenMode(QIODevice::ReadWrite);
964
fprintf(stderr, "SocksClient: server << Success >>\n");
967
if(!d->recvBuf.isEmpty()) {
968
appendRead(d->recvBuf);
969
d->recvBuf.resize(0);
974
void SocksClient::grantUDPAssociate(const QString &relayHost, int relayPort)
976
if(d->step != StepRequest || !d->waiting)
981
writeData(sp_set_request(relayHost, relayPort, RET_SUCCESS));
983
setOpenMode(QIODevice::ReadWrite);
985
fprintf(stderr, "SocksClient: server << Success >>\n");
988
if(!d->recvBuf.isEmpty())
989
d->recvBuf.resize(0);
992
QHostAddress SocksClient::peerAddress() const
994
return d->sock.peerAddress();
997
quint16 SocksClient::peerPort() const
999
return d->sock.peerPort();
1002
QString SocksClient::udpAddress() const
1007
quint16 SocksClient::udpPort() const
1012
SocksUDP *SocksClient::createUDP(const QString &host, int port, const QHostAddress &routeAddr, int routePort)
1014
return new SocksUDP(this, host, port, routeAddr, routePort);
1017
//----------------------------------------------------------------------------
1019
//----------------------------------------------------------------------------
1020
class SocksServer::Private
1023
Private(SocksServer *_q) :
1029
QList<SocksClient*> incomingConns;
1033
SocksServer::SocksServer(QObject *parent)
1036
d = new Private(this);
1038
connect(&d->serv, SIGNAL(connectionReady(int)), SLOT(connectionReady(int)));
1041
SocksServer::~SocksServer()
1044
while (d->incomingConns.count()) {
1045
delete d->incomingConns.takeFirst();
1050
bool SocksServer::isActive() const
1052
return d->serv.isActive();
1055
bool SocksServer::listen(quint16 port, bool udp)
1058
if(!d->serv.listen(port))
1061
d->sd = new QUdpSocket(this);
1062
if(!d->sd->bind(QHostAddress::LocalHost, port)) {
1068
connect(d->sd, SIGNAL(readyRead()), SLOT(sd_activated()));
1073
void SocksServer::stop()
1080
int SocksServer::port() const
1082
return d->serv.port();
1085
QHostAddress SocksServer::address() const
1087
return d->serv.address();
1090
SocksClient *SocksServer::takeIncoming()
1092
if(d->incomingConns.isEmpty())
1095
SocksClient *c = d->incomingConns.takeFirst();
1097
// we don't care about errors anymore
1098
disconnect(c, SIGNAL(error(int)), this, SLOT(connectionError()));
1100
// don't serve the connection until the event loop, to give the caller a chance to map signals
1101
QTimer::singleShot(0, c, SLOT(serve()));
1106
void SocksServer::writeUDP(const QHostAddress &addr, int port, const QByteArray &data)
1109
d->sd->writeDatagram(data.data(), data.size(), addr, port);
1113
void SocksServer::connectionReady(int s)
1115
SocksClient *c = new SocksClient(s, this);
1116
connect(c, SIGNAL(error(int)), this, SLOT(connectionError()));
1117
d->incomingConns.append(c);
1121
void SocksServer::connectionError()
1123
SocksClient *c = (SocksClient *)sender();
1124
d->incomingConns.removeAll(c);
1128
void SocksServer::sd_activated()
1130
while (d->sd->hasPendingDatagrams()) {
1131
QByteArray datagram;
1132
QHostAddress sender;
1134
datagram.resize(d->sd->pendingDatagramSize());
1135
d->sd->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
1136
incomingUDP(sender.toString(), senderPort, d->sd->peerAddress(), d->sd->peerPort(), datagram);