MasterofProject

How to build VPN connected to the local area network in Tencent cloud platform

label Tencent cloud
2398 people read comment(0) Collection report

Recently needed to use Tencent cloud platform, learn a lot after the discovery of CVM must use the specified agent after Using SSH login, also SSH login also need a dynamic password, so that the operation and maintenance is very convenient, so they want to get a VPN will CVM and offline environment to get a local area network. So there is a problem, the OpenVPN server put where, the test found that CVM is not only into, that do not have direct access to the network, unless there is a request in. So obviously CVM can only do a server, but new problems again, CVM server TCP protocol requires modification to the application layer protocol, must pass a TGW head, this is let people depressed the, don't to modify OpenVPN code? This is obviously not, so they want to simply write a proxy got, its principle is very simple, as a transparent proxy, only different is, when it as a client, after establishing a connection immediately to the server to send a TGW head; when to kill it as the server, will establish a connection after the receipt of the TGW. When these things after it is a pure transparent agent the. Such a program is not difficult to write, with a golang will be able to write a, the following is a written procedure

  1. Main package
  2.   
  3. Import (
  4. "Flag"
  5. "Fmt"
  6. "Log"
  7. "Net"
  8. "Time"
  9. )
  10.   
  11. / / configuration parameters
  12. TConfig struct type {
  13. TargetAddr string / / target address, such as app12345.qzoneapp.com:80
  14. SourceAddr string / / source address, the address is local monitoring
  15. LogFile string / / log file.
  16. ActAsServer bool / / whether as a server, and if so, parameters need to be targetAddr to TGW
  17. Int bufferSize
  18. }
  19.   
  20. (VaR
  21. TConfig gConfig
  22. *net.TCPAddr gTargetAddr
  23. *net.TCPAddr gSourceAddr
  24. )
  25.   
  26. Const (
  27. TGW_PREFIX = "tgw_l7_forward"
  28. TGW_HEADER_SIZE = 1024 * 4
  29. TGW_HEADER_SEG_COUNT = 3
  30. )
  31.   
  32. / / initialization parameters
  33. InitArgs bool () func {
  34. Flag.StringVar (&gConfig.targetAddr, "t", ": 54321", "target address, such as app12345.qzoneapp.com:80")
  35. Flag.StringVar (&gConfig.sourceAddr, "s", ": 12345", "local listening address, such as 192.168.1.200:8080")
  36. //flag.StringVar (&gConfig.logFile, "L", "/tmp/tgwProxy.log", "log output address")
  37. Flag.BoolVar (&gConfig.actAsServer, "a", false, "if it is a server, if it is, you need to send the parameters in TGW to targetAddr")
  38. Flag.IntVar (&gConfig.bufferSize, "B", 1024*1024, "cache size")
  39. Flag.Parse ()
  40.   
  41. Err error var
  42. Err, gSourceAddr = net.ResolveTCPAddr ("tcp4", gConfig.sourceAddr)
  43. Err if! = nil {
  44. Fmt.Printf ("TCP address:%s failed:%s\n resolve", gConfig.sourceAddr, err.Error (), ()
  45. False return
  46. }
  47.   
  48. Err, gTargetAddr = net.ResolveTCPAddr ("tcp4", gConfig.targetAddr)
  49. Err if! = nil {
  50. Fmt.Printf ("TCP address:%s failed:%s\n resolve", gConfig.targetAddr, err.Error (), ()
  51. False return
  52. }
  53.   
  54. GConfig.bufferSize if < 1 {
  55. Fmt.Printf ("size:%d is too small\n buffer", gConfig.bufferSize)
  56. False return
  57. }
  58.   
  59. True return
  60. }
  61.   
  62. / / initialize server
  63. RunServer func () {
  64. Err, listener: = net.ListenTCP ("tcp4", gSourceAddr)
  65. Err if! = nil {
  66. Fmt.Printf ("on TCP address:%s failed:%s\n listen", gConfig.sourceAddr, err.Error (), ()
  67. Return
  68. }
  69. Log.Printf ("started server")
  70. {for
  71. Err, Conn: = listener.AcceptTCP ()
  72. Err if! = nil {
  73. Log.Printf ("TCP connection failed:%s accept", err.Error ())
  74. Time.Sleep (1000000000)
  75. }
  76.   
  77. Log.Printf ("one connection get")
  78. conn.setkeepalive(真的)
  79. conn.setnodelay(真的)
  80.   
  81. 如果gconfig.actasserver {
  82. 去doserver(CONN)
  83. { }
  84. 去doclient(CONN)
  85. }
  86. }
  87. }
  88.   
  89. / /将所有数据写入连接中
  90. 功能writealldata(CONN净。Conn,缓冲[ ]字节)误差{
  91. 偏移量:= 0
  92. 长度:= Len(缓冲区)
  93. 为偏移<长度{
  94. 字节错误:= conn.write(缓冲区偏移量:[长度])
  95. 如果犯错!=无{
  96. 日志。printf(“写目标:%s失败:%s”,康涅狄格州remoteaddr()。string(),犯错。error())
  97. 返回错误
  98. }
  99. 偏移量+ =字节
  100. }
  101. / /日志。printf(“%d字节写的连接”,偏移)
  102. 零回报
  103. }
  104.   
  105. / /处理服务器事务
  106. 功能doserver(CONN净。Conn){
  107. 推迟handlepanic()
  108. / /去掉TGW的头
  109. 缓冲区:为使([ ]字节,tgw_header_size)
  110. 长度错误:= conn.read(缓冲区)
  111. 如果犯错!=无{
  112. 日志。printf(“读取客户端失败:%s”,是错误的。error())
  113. 返回
  114. }
  115. segcount:= 0
  116. 我:= 1;我<长度;我+ + {
  117. 如果缓冲区[我] = = '\n'和缓冲[·] = =“R”{
  118. segcount + +
  119. 如果segcount = = tgw_header_seg_count {
  120. 缓冲=缓冲[我+ 1:长度]
  121. 打破
  122. }
  123. }
  124. }
  125.   
  126. 如果segcount < tgw_header_seg_count {
  127. 日志。printf(“无效TGW标题:%s”字符串(缓冲[长度] 0:))
  128. 返回
  129. }
  130.   
  131. targetconn,错误:=净。dialtcp(“tcp4”,零,gtargetaddr)
  132. 如果犯错!=无{
  133. 日志。printf(“连接到目标:%s失败:%s”,gtargetaddr。string(),犯错。error())
  134. 返回
  135. }
  136.   
  137. 日志。printf(“连接到服务器:%s成功”,gtargetaddr。string())
  138.   
  139. / /写剩下的字段
  140. 错误=writealldata(targetconn,缓冲)
  141. 如果犯错!=无{
  142. 返回
  143. }
  144.   
  145. / /源请求到目标连接,即写请求
  146. 去proxytransfer(Conn,targetconn)
  147.   
  148. / /目标响应到源连接,即写响应
  149. 去proxytransfer(targetconn,Conn)
  150. }
  151.   
  152. / /将从sourceconn中读到的数据写给targetconn
  153. 功能proxytransfer(sourceconn净。Conn,targetconn净。Conn){
  154. 推迟handlepanic()
  155. 缓冲区:为使([ ]字节,基于缓存。)
  156. {
  157. 长度错误:= sourceconn读(缓冲区)。
  158. 如果犯错!=无{
  159. 日志。printf(“阅读来源:%s失败:%s”,sourceconn。remoteaddr()。string(),犯错。error())
  160. targetconn。()
  161. 返回
  162. }
  163. / /日志。printf(“%d字节读取源连接,长度)
  164.   
  165. 错误=writealldata(targetconn [ 0 ],缓冲区长度)
  166. 如果犯错!=无{
  167. targetconn。()
  168. 返回
  169. }
  170. }
  171. }
  172.   
  173. / /处理客户端事务
  174. 功能doclient(CONN净。Conn){
  175. 推迟handlepanic()
  176. / /建立连接到目录地址
  177. targetconn,错误:=净。dialtcp(“tcp4”,零,gtargetaddr)
  178. 如果犯错!=无{
  179. 日志。printf(“连接到目标:%s失败:%s”,gtargetaddr。string(),犯错。error())
  180. 返回
  181. }
  182.   
  183. 日志。printf(“连接到服务器:%s成功”,gtargetaddr。string())
  184.   
  185. / /加上TGW的头
  186. tgwheader:= tgw_prefix +“\ R \ NHOst:“+ +”gconfig.targetaddr \r\n \r\n”
  187. 日志。printf(“送tgwheader:%s服务器:%s”,tgwheader,gtargetaddr。string())
  188. 缓冲区:= []字节(tgwheader)
  189. 错误=writealldata(targetconn,缓冲)
  190. 如果犯错!=无{
  191. 返回
  192. }
  193.   
  194. / /源请求到目标连接,即写请求
  195. 去proxytransfer(Conn,targetconn)
  196.   
  197. / /目标响应到源连接,即写响应
  198. 去proxytransfer(targetconn,Conn)
  199. }
  200.   
  201. / /初始化日志
  202. 功能initlogger() bool {
  203. 日志。setflags(log.ldate |日志。lshortfile |日志。lmicroseconds |日志。时间)
  204. 日志。printf(“记录器初始化”)
  205. 返回真
  206. }
  207.   
  208. 功能handlepanic() {
  209. 错误:= recover()
  210. 如果犯错!=无{
  211. 日志。printf(“捕获的恐慌:%s,错误(错误)。error())
  212. }
  213. }
  214.   
  215. 功能main() {
  216. 如果!initargs() | |!initlogger() {
  217. 返回
  218. }
  219. runserver()
  220. }

这样的话,在CVM上启动一个服务器端,监听到127.0.0.1:1179上,然后再在CVM上启动一个代理让它代理到这个端口上,而外部端口则监听到CVM的绑定端口上。

同样的,在本地启动一个代理,让它代理到CVM的绑定域名和端口上,然后OpenVPN客户端连到代理的监听端口上,这样果然两台机器就弄到一个局域网里了。


接下来你就只需要在CVM里建一些”合适”的账号就可以不用动态密码直接像局域网一样登录了。

猜你在找
查看评论
*以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:20764次
    • 积分:二百一十七
    • 等级:
    • 排名:千里之外
    • 原创:0篇
    • 转载:9篇
    • 译文:0篇
    • 评论:2条
    文章存档
    最新评论