转载

穿透内网的反弹代理

舍友滚去实习了,恰好又要选课。学校的教务系统似乎无法从外网访问,于是便考虑给他们搞个代理。

一般情况下,代理服务器需要运行在内网,在公网边界暴露访问端口以便外网用户得以访问。但是很显然我没有校网边界路由器的权限,不可能去改防火墙。

好在我有一台VPS,在这种双方用户无法直连的情况下,就只能反过来利用第三台机器做中转了。思路很直接,校网的代理主动连接到中转服务器,再由中转服务器提供代理服务接收请求转发到校网的代理服务器中。

这种做法被叫做“反弹代理”。

一、搭建sock5反弹代理

在网上搜了一圈,发现有一个软件 ssocks 能支持反弹代理。遂下载编译。

在VPS上开放了端口8888用于反弹代理连接,并在1080端口提供Sock5代理服务:

Shell

./rcsocks -l 1080 -p 8888 -vv
./rcsocks-l1080-p8888-vv 

在校网使用树莓派架设一个反弹代理的客户端,启动时自动连接到VPS的8888端口:

Shell

./rssocks -vv -s bakachu.cn:8888
./rssocks-vv-sbakachu.cn:8888 

这样,反弹代理就搭建完毕了,之后只要用代理客户端连接VPS的1080端口就能获得服务。

二、转换成HTTP代理

但是Sock5代理的功能太强大,如果只提供HTTP代理服务就要做转换了。这里,我直接使用tengine配合其上的lua模块编写一个小的转换脚本来将HTTP请求转到本地的sock5代理上。

tengine配置:

server {  listen 8080;  server_name proxy.bakachu.cn;   charset utf-8;   access_log /home/ngx-logs/proxy.access.log;  error_log /home/ngx-logs/proxy.error.log;   location / {   lua_socket_read_timeout 300s;    default_type text/html;   content_by_lua_file /data/proxy.lua;  } }
server{ listen8080; server_name proxy.bakachu.cn;   charset utf-8;   access_log/home/ngx-logs/proxy.access.log; error_log/home/ngx-logs/proxy.error.log;   location/{ lua_socket_read_timeout300s;   default_type text/html; content_by_lua_file/data/proxy.lua; } } 

lua脚本:

Lua

local socks5 = require("resty.socks5") local base64 = require("base64")  local headers = ngx.req.get_headers() local proxy_auth = headers["Proxy-Authorization"] if proxy_auth == nil or proxy_auth == "" then  ngx.header["Proxy-Authenticate"] = 'Basic realm="Passwd required."'  ngx.exit(407) else  local _, _, base64enc = string.find(proxy_auth, "Basic (.+)")  local authinfo = base64.decode(base64enc)  local _, _, username, passwd = string.find(authinfo, "(.+):(.+)")   if username ~= "proxy_username" or passwd ~= "proxy_passwd" then   ngx.header["Proxy-Authorization"] = ""   ngx.header["Proxy-Authenticate"] = 'Basic realm="Bad username or password."'   ngx.exit(407)  else   socks5.handle_request("127.0.0.1", 1080)  end end
localsocks5=require("resty.socks5") localbase64=require("base64")   localheaders=ngx.req.get_headers() localproxy_auth=headers["Proxy-Authorization"] ifproxy_auth==nilorproxy_auth==""then ngx.header["Proxy-Authenticate"]='Basic realm="Passwd required."' ngx.exit(407) else local_,_,base64enc=string.find(proxy_auth,"Basic (.+)") localauthinfo=base64.decode(base64enc) local_,_,username,passwd=string.find(authinfo,"(.+):(.+)")   ifusername~="proxy_username"orpasswd~="proxy_passwd"then ngx.header["Proxy-Authorization"]="" ngx.header["Proxy-Authenticate"]='Basic realm="Bad username or password."' ngx.exit(407) else socks5.handle_request("127.0.0.1",1080) end end 

这样,就可以通过http://proxy.bakachu.cn:8080和用户名密码来访问sock5代理了。

参考:

  1. Socks代理反弹突破内网( http://www.freebuf.com/articles/system/12182.html )
  2. resty.socks5( https://github.com/starius/lua-resty-socks5 )
正文到此结束
Loading...