main.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. package main
  2. import (
  3. "container/list"
  4. "encoding/json"
  5. "errors"
  6. "flag"
  7. "fmt"
  8. "io"
  9. "jycdp"
  10. "log"
  11. "net"
  12. "net/http"
  13. "strconv"
  14. "strings"
  15. "sync"
  16. "time"
  17. )
  18. const (
  19. tun_status_normal = iota
  20. tun_status_busy
  21. tun_status_idle
  22. )
  23. type (
  24. //Springboard 跳板
  25. Springboard struct {
  26. TcpServeAddr string `yaml:"address"`
  27. Cache *list.List
  28. Proxy *IpItem //代理地址
  29. }
  30. //Config
  31. Config struct {
  32. MonitorAddress string `yaml:"monitor_address"`
  33. ConnectTimeout int64 `yaml:"connect_timeout"`
  34. SpringboardesPortRange [2]int `yaml:"portrange"`
  35. PublicIpAddr string `yaml:"public_ip_address"`
  36. }
  37. //流量监听 ,只监听请求端
  38. Monitor struct {
  39. s *Springboard
  40. }
  41. //
  42. MyMux struct{}
  43. )
  44. // Write 实现写接口
  45. func (m *Monitor) Write(b []byte) (int, error) {
  46. if strings.Contains(string(b), "pleasechangemyip.com") {
  47. m.s.ChangeIp()
  48. }
  49. return len(b), nil
  50. }
  51. var (
  52. configFile = flag.String("c", "./config.yaml", "配置文件")
  53. config *Config = new(Config)
  54. status []int
  55. tunLock = new(sync.RWMutex)
  56. )
  57. // forward 流量转发
  58. func (s *Springboard) forward(src, dest io.ReadWriteCloser) {
  59. defer func() {
  60. if src != nil {
  61. _ = src.Close()
  62. }
  63. if dest != nil {
  64. _ = dest.Close()
  65. }
  66. }()
  67. if src == nil || dest == nil {
  68. return
  69. }
  70. _, _ = io.Copy(io.MultiWriter(&Monitor{s}, src), dest)
  71. }
  72. // processClient 处理客户端请求
  73. func (s *Springboard) ProcessClient(client net.Conn) {
  74. defer func() {
  75. if err := recover(); err != nil {
  76. fmt.Printf("{err %v}", err)
  77. }
  78. }()
  79. var targetConn net.Conn
  80. var err error
  81. for {
  82. //默认复用上一次对可用IP
  83. targetConn, err = net.DialTimeout("tcp",
  84. s.Proxy.Raw,
  85. time.Duration(config.ConnectTimeout)*time.Second)
  86. if err == nil {
  87. break
  88. }
  89. //TODO 移除有问题的链接
  90. //roulette.ClearBadProxy(s.Proxy.Index)
  91. //跳板主动切换IP
  92. s.Proxy, _ = roulette.Get()
  93. }
  94. s.Cache.PushBack([2]net.Conn{client, targetConn})
  95. go s.forward(client, targetConn)
  96. go s.forward(targetConn, client)
  97. }
  98. // StartServe 开启TCP服务
  99. func (s *Springboard) StartServe() {
  100. s.Proxy, _ = roulette.Get()
  101. log.Println(s.TcpServeAddr, s.Proxy.Raw)
  102. conn, err := net.Listen("tcp", s.TcpServeAddr)
  103. if err != nil {
  104. log.Println(err.Error())
  105. return
  106. }
  107. log.Println("springboard listen:", s.TcpServeAddr)
  108. for {
  109. client, err := conn.Accept()
  110. if err != nil {
  111. log.Println("Listen failed: %v\n", err)
  112. continue
  113. }
  114. go s.ProcessClient(client)
  115. }
  116. }
  117. // ChangeIp 切换IP
  118. func (s *Springboard) ChangeIp() {
  119. s.Proxy, _ = roulette.Get()
  120. fmt.Print("C")
  121. //fmt.Printf("(%s)", s.Proxy.Raw)
  122. for e := s.Cache.Front(); e != nil; e = e.Next() {
  123. connes, _ := e.Value.([2](net.Conn))
  124. if connes[0].Close() != nil {
  125. _ = connes[0].Close()
  126. }
  127. if connes[1].Close() != nil {
  128. _ = connes[0].Close()
  129. }
  130. }
  131. }
  132. // Apply 批量申请代理端口资源,用于启动docker,传入proxy_server
  133. func Apply(length int) (ret []string, err error) {
  134. tunLock.Lock()
  135. defer tunLock.Unlock()
  136. ret = make([]string, length, length)
  137. pos, start := 0, config.SpringboardesPortRange[0]
  138. tmp := make([]int, length, length)
  139. for i, v := range status {
  140. if v == tun_status_idle {
  141. //status[i] = tun_status_busy
  142. tmp[pos] = i
  143. pos += 1
  144. }
  145. if pos == length {
  146. break
  147. }
  148. }
  149. if pos < length-1 {
  150. return nil, errors.New("没有足够的tun资源")
  151. }
  152. //改状态
  153. for i, v := range tmp {
  154. status[v] = tun_status_busy
  155. ret[i] = fmt.Sprintf("%s:%d", config.PublicIpAddr, start+v)
  156. }
  157. return
  158. }
  159. // Repay 归还释放tun资源
  160. func Repay(address []string) {
  161. ports := make([]int, len(address), len(address))
  162. for i, v := range address {
  163. ports[i], _ = strconv.Atoi(strings.Split(v, ":")[1])
  164. }
  165. tunLock.Lock()
  166. defer tunLock.Unlock()
  167. start := config.SpringboardesPortRange[0]
  168. for _, v := range ports {
  169. status[v-start] = tun_status_idle
  170. }
  171. }
  172. // monitor
  173. func monitor() {
  174. //申请tun端口
  175. http.HandleFunc("/apply", func(w http.ResponseWriter, r *http.Request) {
  176. lenStr := r.FormValue("len")
  177. if lenStr == "" {
  178. lenStr = "1"
  179. }
  180. length, _ := strconv.Atoi(lenStr)
  181. ret, err := Apply(length)
  182. if err != nil {
  183. w.WriteHeader(http.StatusInternalServerError)
  184. fmt.Fprint(w, "没有足够的tun资源,请减少申请数量")
  185. } else {
  186. json.NewEncoder(w).Encode(ret)
  187. }
  188. })
  189. http.HandleFunc("/repay", func(w http.ResponseWriter, r *http.Request) {
  190. data := struct {
  191. Data []string `json:"address"`
  192. }{}
  193. json.NewDecoder(r.Body).Decode(&data)
  194. Repay(data.Data)
  195. fmt.Fprint(w, "ok")
  196. })
  197. http.ListenAndServe(config.MonitorAddress, nil)
  198. }
  199. // init 初始化
  200. func init() {
  201. flag.Parse()
  202. jycdp.LoadConfig(*configFile, config)
  203. length := config.SpringboardesPortRange[1] - config.SpringboardesPortRange[0] + 1
  204. status = make([]int, length, length)
  205. //全部设置为闲
  206. for i, _ := range status {
  207. status[i] = tun_status_idle
  208. }
  209. reloadProxies()
  210. go watch()
  211. }
  212. // main
  213. func main() {
  214. //
  215. for i := config.SpringboardesPortRange[0]; i <= config.SpringboardesPortRange[1]; i++ {
  216. s := &Springboard{
  217. TcpServeAddr: fmt.Sprintf(":%d", i),
  218. Cache: list.New(),
  219. }
  220. go s.StartServe()
  221. }
  222. monitor()
  223. //
  224. }