Created
May 21, 2018 05:47
-
-
Save alexd1971/2ac145546ee72f713e0c9fb6acddf425 to your computer and use it in GitHub Desktop.
Socks5 communication in dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'dart:io'; | |
/// Фазы установки соединения с socks5-сервером | |
enum Socks5 {init, auth, connect} | |
Future main() async { | |
String targetHost = 'delidela.com'; | |
int targetPort = 443; | |
String socksLogin = 'login'; | |
String socksPassword = 'password'; | |
// Устанавливаем TCP-соединение с socks5-сервером | |
Socket socket = await Socket.connect('socks5.host', 7777); | |
// Здесь фиксируется, на каком этапе находится общение с сервером | |
Socks5 step; | |
// Результат запроса к серверу | |
int result; | |
// Ip-адрес, выданный сервером после усешной установки соединения | |
InternetAddress ip; | |
// Порт, выданный сервером, после успешной установки соединения | |
int port; | |
// Комплитер необходим для синхронизации запросов | |
Completer completer; | |
// Слушаем, что отвечает сервер | |
// data - это List<int> (байты с информацией от сервера) | |
socket.listen((data) async { | |
// Результат запроса (успех/неудача и т.п.) передается в data[1] | |
result = data[1]; | |
// Если выполнялась команда CONNECT, то из ответа сервера можно выделить ip и port, | |
// выданные сервером для общения с целевым хостом | |
if (step == Socks5.connect) { | |
// data[3] определяет в каком формате передан адрес | |
if (data[3] == 1) { // data[3] == 1 - адрес в формате IPv4 | |
ip = new InternetAddress(data.sublist(4, 8).join('.')); | |
} else if (data[3] == 3) { //data[3] == 3 - адрес в виде доменного имени | |
ip = (await InternetAddress.lookup( | |
new String.fromCharCodes(data.sublist(5, 5+data[4])), | |
type: InternetAddressType.IP_V4) | |
)[0]; | |
} | |
port = int.parse('0x' + data.sublist(data.length-2).map((int byte) => byte.toRadixString(16)).join()); | |
} | |
completer.complete(); | |
}); | |
// Первый шаг | |
step = Socks5.init; | |
print('Подключение к socks5 серверу...'); | |
completer = new Completer(); | |
// Формат запроса можно почитать в RFC 1928 | |
socket.add([0x05, 0x02, 0x00, 0x02]); | |
await completer.future; | |
if (result == 0xff) { | |
print('Указанные методы аутентификации не поддерживаются'); | |
socket.close(); | |
exit(1); | |
} | |
print('готово'); | |
// Если сервер выбрал метод аутентификации по логину и пароль (2), | |
// то выполняем аутентификацию | |
if (result == 2) { | |
step = Socks5.auth; | |
print('Аутентификация'); | |
completer = new Completer(); | |
List<int> loginBytes = socksLogin.codeUnits; | |
List<int> passwordBytes = socksPassword.codeUnits; | |
// Фомирование запроса на аутентификацию | |
// Формат запроса см. RFC 1929 | |
List<int> authRequest = [1]; | |
authRequest.add(loginBytes.length); | |
authRequest.addAll(loginBytes); | |
authRequest.add(passwordBytes.length); | |
authRequest.addAll(passwordBytes); | |
socket.add(authRequest); | |
await completer.future; | |
if (result != 0) { | |
print('Неверный логин или пароль'); | |
socket.close(); | |
exit(1); | |
} | |
print('Ok'); | |
} | |
// Устанавливаем подключение к целевому хосту | |
step = Socks5.connect; | |
print('Устанавливаем подключение...'); | |
completer = new Completer(); | |
List<int> targetHostBytes = targetHost.codeUnits; | |
String hexTargetPortString = targetPort.toRadixString(16).padLeft(4, '0'); | |
List<int> targetPortBytes = [ | |
hexTargetPortString.substring(0, 2), | |
hexTargetPortString.substring(2) | |
].map((String byte) => int.parse(byte)); | |
List<int> connectRequest = [5, 1, 0, 3]; | |
connectRequest.add(targetHostBytes.length); | |
connectRequest.addAll(targetHostBytes); | |
connectRequest.addAll(targetPortBytes); | |
socket.add(connectRequest); | |
await completer.future; | |
print(ip); | |
print(port); | |
// Тут, видимо, должна быть коммуникация с целевым хостом | |
socket.close(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment