Signed-off-by: arraykeys@gmail.com <arraykeys@gmail.com>

This commit is contained in:
arraykeys@gmail.com
2018-01-26 11:03:34 +08:00
parent 2fc750532d
commit 5f0a341d22
7 changed files with 104 additions and 26 deletions

View File

@ -17,6 +17,7 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
- SSH中转,HTTP(S),SOCKS5代理支持SSH中转,上级Linux服务器不需要任何服务端,本地一个proxy即可开心上网.
- [KCP](https://github.com/xtaci/kcp-go)协议支持,HTTP(S),SOCKS5代理支持KCP协议传输数据,降低延迟,提升浏览体验.
- 集成外部APIHTTP(S),SOCKS5代理认证功能可以与外部HTTP API集成可以方便的通过外部系统控制代理用户
- 透明HTTP(S)代理,支持直接把域名解析到proxy监听的ip,然后proxy就会帮你代理访问需要访问的HTTP(S)网站.如果配合iptables,在网关直接把出去的80,443方向的流量转发到proxy,就能实现无感知的智能路由器代理.
### Why need these?
- 当由于某某原因,我们不能访问我们在其它地方的服务,我们可以通过多个相连的proxy节点建立起一个安全的隧道访问我们的服务.  
@ -69,7 +70,9 @@ Proxy是golang实现的高性能http,https,websocket,tcp,udp,socks5代理服务
- [1.7.1 用户名和密码的方式](#171-ssh用户名和密码的方式)
- [1.7.2 用户名和密钥的方式](#172-ssh用户名和密钥的方式)
- [1.8 KCP协议传输](#18kcp协议传输)
- [1.9 查看帮助](#19查看帮助)
- [1.9 HTTP(S)透明代理(域名解析)](#19https透明代理域名解析)
- [1.10 HTTP(S)透明代理(iptables转发)](#110https透明代理iptables转发)
- [1.11 查看帮助](#111查看帮助)
- [2. TCP代理](#2tcp代理)
- [2.1 普通一级TCP代理](#21普通一级tcp代理)
- [2.2 普通二级TCP代理](#22普通二级tcp代理)
@ -122,7 +125,7 @@ curl -L https://raw.githubusercontent.com/snail007/goproxy/master/install_auto.s
下载地址:https://github.com/snail007/goproxy/releases
```shell
cd /root/proxy/
wget https://github.com/snail007/goproxy/releases/download/v4.1/proxy-linux-amd64.tar.gz
wget https://github.com/snail007/goproxy/releases/download/v4.2/proxy-linux-amd64.tar.gz
```
#### **2.下载自动安装脚本**
```shell
@ -266,6 +269,66 @@ KCP协议需要-B参数设置一个密码用于加密解密数据
`./proxy http -t tcp -p ":8080" -T kcp -P "22.22.22.22:38080" -B mypassword`
那么访问本地的8080端口就是访问VPS上面的代理端口38080,数据通过kcp协议传输.
#### **1.9 HTTP(S)透明代理(域名解析)**
proxy不仅支持在其他软件里面通过设置代理的方式,为其他软件提供代理服务,而且支持直接把请求的网站域名解析到proxy监听的ip上,然后proxy监听80和443端口,那么proxy就会自动为你代理访问需要访问的HTTP(S)网站.
使用方式:
在"最后一级proxy代理"的机器上,因为proxy要伪装成所有网站,网站默认的端口HTTP是80,HTTPS是443,让proxy监听80和443端口即可.参数-p多个地址用逗号分割.
`./proxy http -t tcp -p :80,:443`
这个命令就在机器上启动了一个proxy代理,同时监听80和443端口,既可以当作普通的代理使用,也可以直接把需要代理的域名解析到这个机器的IP上.
如果有上级代理那么参照上面教程设置上级即可,使用方式完全一样.
`./proxy http -t tcp -p :80,:443 -T tls -P "2.2.2.2:33080" -C proxy.crt -K proxy.key`
注意:
proxy所在的服务器的DNS解析结果不能受到自定义的解析影响,不然就死循环了.
#### **1.10 HTTP(S)透明代理(iptables转发)**
该模式需要具有一定的网络基础,相关概念不懂的请自行搜索解决.
假设proxy现在在路由器上运行,启动命令如下:
`./proxy http -t tcp -p :33080 -T tls -P "2.2.2.2:33090" -C proxy.crt -K proxy.key`
然后添加iptables规则,下面是参考规则:
```shell
#上级proxy服务端服务器IP地址:
proxy_server_ip=2.2.2.2
#路由器运行proxy监听的端口:
proxy_local_port=33080
#下面的就不用修改了
#create a new chain named PROXY
iptables -t nat -N PROXY
# Ignore your PROXY server's addresses
# It's very IMPORTANT, just be careful.
iptables -t nat -A PROXY -d $proxy_server_ip -j RETURN
# Ignore LANs IP address
iptables -t nat -A PROXY -d 0.0.0.0/8 -j RETURN
iptables -t nat -A PROXY -d 10.0.0.0/8 -j RETURN
iptables -t nat -A PROXY -d 127.0.0.0/8 -j RETURN
iptables -t nat -A PROXY -d 169.254.0.0/16 -j RETURN
iptables -t nat -A PROXY -d 172.16.0.0/12 -j RETURN
iptables -t nat -A PROXY -d 192.168.0.0/16 -j RETURN
iptables -t nat -A PROXY -d 224.0.0.0/4 -j RETURN
iptables -t nat -A PROXY -d 240.0.0.0/4 -j RETURN
# Anything to port 80 443 should be redirected to PROXY's local port
iptables -t nat -A PROXY -p tcp --dport 80 -j REDIRECT --to-ports $proxy_local_port
iptables -t nat -A PROXY -p tcp --dport 443 -j REDIRECT --to-ports $proxy_local_port
# Apply the rules to nat client
iptables -t nat -A PREROUTING -p tcp -j PROXY
# Apply the rules to localhost
iptables -t nat -A OUTPUT -p tcp -j PROXY
```
- 清空整个链 iptables -F 链名比如iptables -t nat -F SHADOWSOCKS
- 删除指定的用户自定义链 iptables -X 链名 比如 iptables -t nat -X SHADOWSOCKS
- 从所选链中删除规则 iptables -D 链名 规则详情 比如 iptables -t nat -D SHADOWSOCKS -d 223.223.192.0/255.255.240.0 -j RETURN
#### **1.9.查看帮助**
`./proxy help http`

View File

@ -64,7 +64,7 @@ func initConfig() (err error) {
httpArgs.Auth = http.Flag("auth", "http basic auth username and password, mutiple user repeat -a ,such as: -a user1:pass1 -a user2:pass2").Short('a').Strings()
httpArgs.PoolSize = http.Flag("pool-size", "conn pool size , which connect to parent proxy, zero: means turn off pool").Short('L').Default("0").Int()
httpArgs.CheckParentInterval = http.Flag("check-parent-interval", "check if proxy is okay every interval seconds,zero: means no check").Short('I').Default("3").Int()
httpArgs.Local = http.Flag("local", "local ip:port to listen").Short('p').Default(":33080").String()
httpArgs.Local = http.Flag("local", "local ip:port to listen,multiple address use comma split,such as: 0.0.0.0:80,0.0.0.0:443").Short('p').Default(":33080").String()
httpArgs.SSHUser = http.Flag("ssh-user", "user for ssh").Short('u').Default("").String()
httpArgs.SSHKeyFile = http.Flag("ssh-key", "private key file for ssh").Short('S').Default("").String()
httpArgs.SSHKeyFileSalt = http.Flag("ssh-keysalt", "salt of ssh private key").Short('s').Default("").String()

View File

@ -5,7 +5,7 @@ if [ -e /tmp/proxy ]; then
fi
mkdir /tmp/proxy
cd /tmp/proxy
wget https://github.com/snail007/goproxy/releases/download/v4.1/proxy-linux-amd64.tar.gz
wget https://github.com/snail007/goproxy/releases/download/v4.2/proxy-linux-amd64.tar.gz
# #install proxy
tar zxvf proxy-linux-amd64.tar.gz

View File

@ -8,7 +8,7 @@ import (
"syscall"
)
const APP_VERSION = "4.1"
const APP_VERSION = "4.2"
func main() {
err := initConfig()

View File

@ -1,5 +1,5 @@
#!/bin/bash
VER="4.1"
VER="4.2"
RELEASE="release-${VER}"
rm -rf .cert
mkdir .cert

View File

@ -9,6 +9,7 @@ import (
"proxy/utils"
"runtime/debug"
"strconv"
"strings"
"time"
"golang.org/x/crypto/ssh"
@ -115,7 +116,9 @@ func (s *HTTP) Start(args interface{}) (err error) {
s.InitOutConnPool()
}
s.InitService()
host, port, _ := net.SplitHostPort(*s.cfg.Local)
for _, addr := range strings.Split(*s.cfg.Local, ",") {
if addr != "" {
host, port, _ := net.SplitHostPort(addr)
p, _ := strconv.Atoi(port)
sc := utils.NewServerChannel(host, p)
if *s.cfg.LocalType == TYPE_TCP {
@ -129,6 +132,8 @@ func (s *HTTP) Start(args interface{}) (err error) {
return
}
log.Printf("%s http(s) proxy on %s", *s.cfg.LocalType, (*sc.Listener).Addr())
}
}
return
}

View File

@ -11,6 +11,7 @@ import (
"log"
"net"
"net/url"
"proxy/utils/sni"
"strings"
"sync"
"time"
@ -306,6 +307,14 @@ func NewHTTPRequest(inConn *net.Conn, bufSize int, isBasicAuth bool, basicAuth *
return
}
req.HeadBuf = buf[:len]
//try sni
serverName, err0 := sni.ServerNameFromBytes(req.HeadBuf)
if err0 == nil {
//sni success
req.Method = "SNI"
req.hostOrURL = "https://" + serverName + ":443"
} else {
//sni fail , try http
index := bytes.IndexByte(req.HeadBuf, '\n')
if index == -1 {
err = fmt.Errorf("http decoder data line err:%s", SubStr(string(req.HeadBuf), 0, 50))
@ -313,6 +322,7 @@ func NewHTTPRequest(inConn *net.Conn, bufSize int, isBasicAuth bool, basicAuth *
return
}
fmt.Sscanf(string(req.HeadBuf[:index]), "%s%s", &req.Method, &req.hostOrURL)
}
if req.Method == "" || req.hostOrURL == "" {
err = fmt.Errorf("http decoder data err:%s", SubStr(string(req.HeadBuf), 0, 50))
CloseConn(inConn)