onions.lua 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. local bit;
  2. pcall(function() bit = require"bit"; end);
  3. if not bit then print("error", "No bit module found. Either LuaJIT 2, lua-bitop or Lua 5.2 is required"); end
  4. local server = require "net.server";
  5. local band = bit.band;
  6. local rshift = bit.rshift;
  7. local lshift = bit.lshift;
  8. local byte = string.byte;
  9. local c = string.char;
  10. local proxy_ip = "127.0.0.1";
  11. local proxy_port = 9150;
  12. function connect_socks5(host_session, connect_host, connect_port)
  13. local conn, handler = socket.tcp();
  14. host_session:debug("Connecting to " .. connect_host .. ":" .. connect_port);
  15. conn:settimeout(5);
  16. local success, err = conn:connect(proxy_ip, proxy_port);
  17. if not success then
  18. host_session:debug(err);
  19. return false;
  20. end
  21. host_session:debug("Connected. Writing handshake...");
  22. conn:send(c(5) .. c(1) .. c(0));
  23. host_session:debug("Waiting for result...");
  24. local data = conn:receive(2);
  25. -- version, method
  26. local request_status = byte(data, 2);
  27. host_session:debug("SOCKS version: "..byte(data, 1));
  28. host_session:debug("Response: "..request_status);
  29. if not request_status == 0x00 then
  30. host_session:debug("Failed to connect to the SOCKS5 proxy. :( It seems to require authentication.");
  31. return false;
  32. end
  33. host_session:debug("Sending connect message.");
  34. -- version 5, connect, (reserved), type: domainname, (length, hostname), port
  35. conn:send(c(5) .. c(1) .. c(0) .. c(3) .. c(#connect_host) .. connect_host);
  36. conn:send(c(rshift(connect_port, 8)) .. c(band(connect_port, 0xff)));
  37. data = conn:receive(5);
  38. request_status = byte(data, 2);
  39. if not request_status == 0x00 then
  40. host_session:debug("Failed to connect to the SOCKS5 proxy. :(");
  41. return false;
  42. end
  43. host_session:debug("Succesfully connected to SOCKS5 proxy.");
  44. local response = byte(data, 4);
  45. if response == 0x01 then
  46. data = data .. conn:receive(5);
  47. -- this means the server tells us to connect on an IPv4 address
  48. local ip1 = byte(data, 5);
  49. local ip2 = byte(data, 6);
  50. local ip3 = byte(data, 7);
  51. local ip4 = byte(data, 8);
  52. local port = band(byte(data, 9), lshift(byte(data, 10), 8));
  53. host_session:debug("Should connect to: "..ip1.."."..ip2.."."..ip3.."."..ip4..":"..port);
  54. if not (ip1 == 0 and ip2 == 0 and ip3 == 0 and ip4 == 0 and port == 0) then
  55. host_session:debug("The SOCKS5 proxy tells us to connect to a different IP, don't know how. :(");
  56. return false;
  57. end
  58. local conn = server.wrapclient(conn, connect_host, connect_port, verse.new_listener(host_session), "*a");
  59. if not conn then
  60. host_session:debug("connection initialisation failed", err);
  61. return false;
  62. end
  63. host_session:set_conn(conn);
  64. return true;
  65. end
  66. return false;
  67. end
  68. print("Onions ready and loaded");
  69. return { connect_socks5 = connect_socks5 }