Skip to content

Commit

Permalink
Merge pull request #30 from sipt/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
sipt committed Sep 18, 2018
2 parents 1867758 + 190950c commit dd42986
Show file tree
Hide file tree
Showing 42 changed files with 1,271 additions and 141,600 deletions.
64 changes: 27 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
- [请求/返回修改及反向代理](#请求/返回修改及反向代理)
- [MitM](#mitm)
- [规则配置](#规则配置)
- [API](static/API.md)
- [Web控制台](#Web控制台)
- [Servers](#servers)
- [DNS Cache](#dns-cache)
Expand Down Expand Up @@ -52,59 +53,36 @@ Shuttle 是基于Go实现的全平台网络代理:
- [ ] 代理功能
- [x] TCP(HTTP/HTTPS)
- [ ] UDP
- [x] 扩展功能
- [x] HTTP抓包
- [x] HTTPS抓包(MITM)
- [x] 反向代理
- [x] 复用连接内请求切分
- [x] 请求头修改
- [x] 返回头修改
- [x] HTTP/HTTPS请求扩展功能
- [x] 抓包(支持MITM)
- [x] URL重写
- [x] 请求/返回修改
- [x] 请求mapping
- [x] 远端多服务器管理
- [x] 服务器分组包含
- [x] 服务器协议支持
- [x] shadowsocks
- [x] SOCKS5
- [x] SOCKS5 over TLS
- [x] 服务器选择
- [x] 服务器分组类型
- [x] RTT(往返时间)选择
- [x] Select(手动)选择
- [x] 代理模式
- [x] 全局代理
- [x] 全局直连
- [x] 全局拒绝
- [x] 全局代理、直连、拒绝
- [x] 规则代理
- [x] DOMAIN:域名全匹配
- [x] DOMAIN-SUFFIX:域名后缀匹配
- [x] DOMAIN-KEYWORD:域名关键字匹配
- [x] IP-CIDR:ip段匹配
- [x] GEO-IP: 支持GEO-IP路由
- [ ] ~~USER-AGENT:HTTP头字匹配~~
- [x] DNS
- [x] static:静态地址映射
- [x] direct:直连DNS解析
- [x] remote:远程服务器DNS解析(防止DNS污染)
- [x] GEO-IP判断
- [x] 外部窗口
- [x] API
- [x] 获取服务器列表
- [x] RTT分组刷新
- [x] Select分组手动选择
- [x] DNS缓存获取
- [x] DNS缓存刷新
- [x] 请求记录列表获取
- [x] 请求记录清空
- [x] CA证书生成
- [x] CA证书下载
- [x] HTTP Dump开关
- [x] MITM 开关
- [x] HTTP/HTTPS抓包内容获取
- [x] 关闭Shuttle
- [x] 重载配置
- [x] 全局代理开关
- [ ] 支持Websocket,完成内容增量更新
- [x] API (详见API文档)
- [x] Web UI
- [x] Web UI (angular6 + ant design)
- [x] Web UI (angular6 + ant design)
- [ ] 优化
- [ ] 内存优化
- [ ] log日志
Expand All @@ -117,7 +95,7 @@ Shuttle 是基于Go实现的全平台网络代理:

#### 准备

下载release文件并解压,完成后目录结构
下载release文件并解压,目录结构

```
shuttle
Expand Down Expand Up @@ -151,6 +129,8 @@ General:

#### 系统配置

如果你可以使用浏览器打开`http://c.sipt.top`显示控制页面可以省略以下操作。

打开系统偏好设置 => 网络 => 高级 => 代理,这里主要设置三个:

* `Web 代理(HTTP)` 设置为`127.0.0.1:8080`(以`http-port: "8080"`为例)
Expand Down Expand Up @@ -199,6 +179,8 @@ General:

#### 系统配置

如果你可以使用浏览器打开`http://c.sipt.top`显示控制页面可以省略以下操作。

打开系统偏好设置 => 网络 => 代理:设置为`127.0.0.1:8080`(以`http-port: "8080"`为例)

此时用浏览器打开`http://c.sipt.top`这时如果已经设置代理成功这个url也是对应到控制台页面。
Expand Down Expand Up @@ -586,7 +568,7 @@ http://c.sipt.top

![Records](static/records.jpg)
查看当前系统的入网所有请求,匹配了哪条规则等
当前只会保留1000条数据,
当前只会保留500条数据,并支持关键字过滤

### 抓包教程

Expand All @@ -596,8 +578,16 @@ HTTPS抓包需要几个步骤:

![Cert](static/cert.jpg)

1. 生成证书:Generate生成证书,每次点击都会生成新的CA证书,生成完成后并保存到配置文件。
2. 点击Download按钮下载下来
3. 加入到系统证书里,并信任它
4. HTTPS抓包要Dump和MITM同时打开(具体哪些可以HTTPS抓包要配合配置文件中`MitM 中的 rules`
1. 生成证书:Generate生成证书,每次点击都会生成新的CA证书,生成完成后自动保存到配置文件中。
2. 点击Download按钮下载下来。
3. 加入到系统证书里,并信任它。
4. 在上图表中列出的是会截取的HTTPS的域名规则,可以自行添加,不匹配表中规则不会拦截抓取。
5. HTTPS抓包要Dump和MITM同时打开。

大文件数据下载:

![large_dump](static/large_dump.jpg)

在输入框内输入文件名,点击下载。

当Dump数据超过2MB时就不会显示数据,只显示文件过大,考虑到网页性能此时最好下载查看。
34 changes: 33 additions & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import (
"time"
"strings"
"runtime/debug"
"github.com/sipt/shuttle/extension/network"
"os"
"os/signal"
"syscall"
)

var (
Expand All @@ -36,11 +40,25 @@ func main() {
//go HandleUDP()
go HandleHTTP(general.HttpPort, general.HttpInterface, StopSocksSignal)
go HandleSocks5(general.SocksPort, general.SocksInterface, StopHTTPSignal)
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
//enable system proxy
EnableSystemProxy(general)
for {
select {
case <-ShutdownSignal:
StopSocksSignal <- true
StopHTTPSignal <- true
//disable system proxy
DisableSystemProxy()
time.Sleep(time.Second)
shuttle.Logger.Info("[Shuttle] is shutdown, see you later!")
return
case <-signalChan:
StopSocksSignal <- true
StopHTTPSignal <- true
//disable system proxy
DisableSystemProxy()
time.Sleep(time.Second)
shuttle.Logger.Info("[Shuttle] is shutdown, see you later!")
return
Expand All @@ -51,12 +69,26 @@ func main() {
if err != nil {
shuttle.Logger.Error("Reload Config failed: ", err)
}
//enable system proxy
EnableSystemProxy(general)
go HandleHTTP(general.HttpPort, general.HttpInterface, StopSocksSignal)
go HandleSocks5(general.SocksPort, general.SocksInterface, StopHTTPSignal)
}
}
}

func EnableSystemProxy(g *shuttle.General) {
network.WebProxySwitch(true, "127.0.0.1", g.HttpPort)
network.SecureWebProxySwitch(true, "127.0.0.1", g.HttpPort)
network.SocksProxySwitch(true, "127.0.0.1", g.SocksPort)
}

func DisableSystemProxy() {
network.WebProxySwitch(false)
network.SecureWebProxySwitch(false)
network.SocksProxySwitch(false)
}

func HandleSocks5(socksPort, socksInterface string, stopHandle chan bool) {
listener, err := net.Listen("tcp", net.JoinHostPort(socksInterface, socksPort))
if err != nil {
Expand All @@ -83,10 +115,10 @@ func HandleSocks5(socksPort, socksInterface string, stopHandle chan bool) {
}
go func() {
defer func() {
conn.Close()
if err := recover(); err != nil {
shuttle.Logger.Error("[HTTP/HTTPS]panic :", err)
shuttle.Logger.Error("[HTTP/HTTPS]stack :", debug.Stack())
conn.Close()
}
}()
shuttle.Logger.Debug("[SOCKS]Accept tcp connection")
Expand Down
13 changes: 12 additions & 1 deletion config.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,13 @@ func ReloadConfig() (*General, error) {
}

func SetMimt(mitm *Mitm) {
conf.Mitm = mitm
if len(mitm.CA) > 0 {
conf.Mitm.CA = mitm.CA
}
if len(mitm.Key) > 0 {
conf.Mitm.Key = mitm.Key
}
conf.Mitm.Rules = mitm.Rules
SaveToFile()
}

Expand All @@ -84,6 +90,11 @@ func SaveToFile() {
var configFile string
var conf *Config

func GetGeneralConfig() (general General) {
general = *conf.General
return
}

func InitConfig(filePath string) (*General, error) {
configFile = filePath
data, err := ioutil.ReadFile(filePath)
Expand Down
2 changes: 1 addition & 1 deletion conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func FilterByReq(req *Request) (rule *Rule, s *Server, err error) {
err = errors.New(err.Error() + ":" + rule.Policy)
return
}
Logger.Debugf("get server by policy [%s] => %v", rule.Policy, s)
Logger.Debugf("get server by policy [%s] => %v", rule.Policy, s.Name)
}
return
}
Expand Down
25 changes: 13 additions & 12 deletions conn_decorate.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,19 @@ var DefaultTimeOut = 10 * time.Second

//
func DefaultDecorate(c net.Conn, network string) (IConn, error) {
id := util.NextID()
id := util.GetLongID()
return &DefaultConn{
Conn: c,
ID: id,
RecordID: id,
Network: network,
Conn: c,
ID: id,
Network: network,
}, nil
}

func DefaultDecorateForTls(c net.Conn, network string, id int64) (IConn, error) {
return &DefaultConn{
Conn: c,
ID: util.NextID(),
RecordID: id,
Network: network,
Conn: c,
ID: id,
Network: network,
}, nil
}

Expand Down Expand Up @@ -69,7 +67,6 @@ func (c *DefaultConn) Write(b []byte) (n int, err error) {
}
func (c *DefaultConn) Close() error {
Logger.Tracef("[ID:%d] close connection", c.GetID())
boxChan <- &Box{c.GetID(), RecordStatus, RecordStatusCompleted}
return c.Conn.Close()
}

Expand Down Expand Up @@ -180,12 +177,16 @@ type Traffic struct {

func (t *Traffic) Read(b []byte) (n int, err error) {
n, err = t.IConn.Read(b)
boxChan <- &Box{t.GetRecordID(), RecordDown, n}
if t.GetRecordID() > 0 && n > 0 {
boxChan <- &Box{t.GetRecordID(), RecordDown, n}
}
return
}

func (t *Traffic) Write(b []byte) (n int, err error) {
n, err = t.IConn.Write(b)
boxChan <- &Box{t.GetRecordID(), RecordUp, n}
if t.GetRecordID() > 0 && n > 0 {
boxChan <- &Box{t.GetRecordID(), RecordUp, n}
}
return
}
21 changes: 19 additions & 2 deletions controller/api/api_router.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package api

import "github.com/gin-gonic/gin"
import (
"github.com/gin-gonic/gin"
)

func APIRoute(router *gin.RouterGroup, shutdownSingnal chan bool, reloadConfigSignal chan bool) {
//dns
Expand All @@ -17,23 +19,38 @@ func APIRoute(router *gin.RouterGroup, shutdownSingnal chan bool, reloadConfigSi
dump.POST("/allow", SetAllowDump)
dump.GET("/allow", GetAllowDump)
dump.GET("/data/:conn_id", DumpRequest)
dump.GET("/large/:conn_id", DumpLarge)
}

//cert
router.POST("/cert", GenerateCert)
router.GET("/cert", DownloadCert)

//MitM rules
router.GET("/mitm/rules", GetMitMRules)
router.POST("/mitm/rules", AppendMitMRules)
router.DELETE("/mitm/rules", DelMitMRules)

//server
router.GET("/servers", ServerList)
router.POST("/server/select", SelectServer)
router.POST("/server/select/refresh", SelectRefresh)

//general
router.GET("/system/proxy/enable", EnableSystemProxy)
router.GET("/system/proxy/disable", DisableSystemProxy)
router.POST("/shutdown", NewShutdown(shutdownSingnal))
router.POST("/reload", ReloadConfig(reloadConfigSignal))
router.GET("/mode", GetConnMode)
router.POST("/mode/:mode", SetConnMode)
router.GET("/speed", Speed) // 时速

//ws
router.GET("/ws/records", func(ctx *gin.Context) {
WsHandler(ctx.Writer, ctx.Request)
})
router.GET("/ws/speed", func(ctx *gin.Context) {
WsSpeedHandler(ctx.Writer, ctx.Request)
}) // 时速
}

type Response struct {
Expand Down
26 changes: 26 additions & 0 deletions controller/api/cert_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,29 @@ func GenerateCert(ctx *gin.Context) {
}
ctx.JSON(200, response)
}

func GetMitMRules(ctx *gin.Context) {
var response Response
response.Data = shuttle.GetMitMRules()
ctx.JSON(200, response)
}

func AppendMitMRules(ctx *gin.Context) {
d := ctx.Query("domain")
if len(d) > 0 {
shuttle.AppendMitMRules(d)
}
var response Response
response.Data = shuttle.GetMitMRules()
ctx.JSON(200, response)
}

func DelMitMRules(ctx *gin.Context) {
d := ctx.Query("domain")
if len(d) > 0 {
shuttle.RemoveMitMRules(d)
}
var response Response
response.Data = shuttle.GetMitMRules()
ctx.JSON(200, response)
}

0 comments on commit dd42986

Please sign in to comment.