wg.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. package wg
  2. import (
  3. "errors"
  4. "fmt"
  5. "log"
  6. "net"
  7. "os"
  8. "os/exec"
  9. "strings"
  10. "sync"
  11. "time"
  12. "golang.zx2c4.com/wireguard/wgctrl"
  13. "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
  14. )
  15. const (
  16. DefaultMTU = 1280
  17. DefaultWgPort = 51820
  18. DefaultWgKeepAlive = 20 * time.Second
  19. )
  20. // WGIface represents a interface instance
  21. type WGIface struct {
  22. Name string
  23. Port int
  24. MTU int
  25. Device *wgtypes.Device
  26. Address WGAddress
  27. Interface NetInterface
  28. mu sync.Mutex
  29. }
  30. // NetInterface represents a generic network tunnel interface
  31. type NetInterface interface {
  32. Close() error
  33. }
  34. // WGAddress Wireguard parsed address
  35. type WGAddress struct {
  36. IP net.IP
  37. Network *net.IPNet
  38. }
  39. // NewWGIFace Creates a new Wireguard interface instance
  40. func NewWGIFace(iface string, address string, mtu int) (*WGIface, error) {
  41. wgIface := &WGIface{
  42. Name: iface,
  43. MTU: mtu,
  44. mu: sync.Mutex{},
  45. }
  46. wgAddress, err := parseAddress(address)
  47. if err != nil {
  48. return wgIface, err
  49. }
  50. wgIface.Address = wgAddress
  51. err = wgIface.GetWgIface(iface)
  52. if err != nil {
  53. return nil, err
  54. }
  55. return wgIface, nil
  56. }
  57. func (w *WGIface) GetWgIface(iface string) error {
  58. wgClient, err := wgctrl.New()
  59. if err != nil {
  60. return err
  61. }
  62. dev, err := wgClient.Device(iface)
  63. if err != nil {
  64. return err
  65. }
  66. //log.Printf("----> DEVICE: %+v\n", dev)
  67. w.Device = dev
  68. w.Port = dev.ListenPort
  69. return nil
  70. }
  71. func GetWgIfacePubKey(iface string) string {
  72. wgClient, err := wgctrl.New()
  73. if err != nil {
  74. log.Println("Error fetching pub key: ", iface, err)
  75. return ""
  76. }
  77. dev, err := wgClient.Device(iface)
  78. if err != nil {
  79. log.Println("Error fetching pub key: ", iface, err)
  80. return ""
  81. }
  82. return dev.PublicKey.String()
  83. }
  84. // parseAddress parse a string ("1.2.3.4/24") address to WG Address
  85. func parseAddress(address string) (WGAddress, error) {
  86. ip, network, err := net.ParseCIDR(address)
  87. if err != nil {
  88. return WGAddress{}, err
  89. }
  90. return WGAddress{
  91. IP: ip,
  92. Network: network,
  93. }, nil
  94. }
  95. // UpdatePeer updates existing Wireguard Peer or creates a new one if doesn't exist
  96. func (w *WGIface) UpdatePeer(peerKey string, allowedIps []net.IPNet, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error {
  97. w.mu.Lock()
  98. defer w.mu.Unlock()
  99. log.Printf("updating interface %s peer %s: endpoint %s ", w.Name, peerKey, endpoint)
  100. // //parse allowed ips
  101. // _, ipNet, err := net.ParseCIDR(allowedIps)
  102. // if err != nil {
  103. // return err
  104. // }
  105. peerKeyParsed, err := wgtypes.ParseKey(peerKey)
  106. if err != nil {
  107. return err
  108. }
  109. peer := wgtypes.PeerConfig{
  110. PublicKey: peerKeyParsed,
  111. ReplaceAllowedIPs: true,
  112. AllowedIPs: allowedIps,
  113. PersistentKeepaliveInterval: &keepAlive,
  114. PresharedKey: preSharedKey,
  115. Endpoint: endpoint,
  116. }
  117. config := wgtypes.Config{
  118. Peers: []wgtypes.PeerConfig{peer},
  119. }
  120. err = w.configureDevice(config)
  121. if err != nil {
  122. return fmt.Errorf("received error \"%v\" while updating peer on interface %s with settings: allowed ips %s, endpoint %s", err, w.Name, allowedIps, endpoint.String())
  123. }
  124. return nil
  125. }
  126. // configureDevice configures the wireguard device
  127. func (w *WGIface) configureDevice(config wgtypes.Config) error {
  128. wg, err := wgctrl.New()
  129. if err != nil {
  130. return err
  131. }
  132. defer wg.Close()
  133. // validate if device with name exists
  134. _, err = wg.Device(w.Name)
  135. if err != nil {
  136. return err
  137. }
  138. log.Printf("got Wireguard device %s\n", w.Name)
  139. return wg.ConfigureDevice(w.Name, config)
  140. }
  141. // GetListenPort returns the listening port of the Wireguard endpoint
  142. func (w *WGIface) GetListenPort() (*int, error) {
  143. log.Printf("getting Wireguard listen port of interface %s", w.Name)
  144. //discover Wireguard current configuration
  145. wg, err := wgctrl.New()
  146. if err != nil {
  147. return nil, err
  148. }
  149. defer wg.Close()
  150. d, err := wg.Device(w.Name)
  151. if err != nil {
  152. return nil, err
  153. }
  154. log.Printf("got Wireguard device listen port %s, %d", w.Name, d.ListenPort)
  155. return &d.ListenPort, nil
  156. }
  157. // GetRealIface - retrieves tun iface based on reference iface name from config file
  158. func GetRealIface(iface string) (string, error) {
  159. RunCmd("wg show interfaces", false)
  160. ifacePath := "/var/run/wireguard/" + iface + ".name"
  161. if !(FileExists(ifacePath)) {
  162. return "", errors.New(ifacePath + " does not exist")
  163. }
  164. realIfaceName, err := GetFileAsString(ifacePath)
  165. if err != nil {
  166. return "", err
  167. }
  168. realIfaceName = strings.TrimSpace(realIfaceName)
  169. if !(FileExists(fmt.Sprintf("/var/run/wireguard/%s.sock", realIfaceName))) {
  170. return "", errors.New("interface file does not exist")
  171. }
  172. return realIfaceName, nil
  173. }
  174. // FileExists - checks if file exists locally
  175. func FileExists(f string) bool {
  176. info, err := os.Stat(f)
  177. if os.IsNotExist(err) {
  178. return false
  179. }
  180. if err != nil && strings.Contains(err.Error(), "not a directory") {
  181. return false
  182. }
  183. if err != nil {
  184. log.Println(0, "error reading file: "+f+", "+err.Error())
  185. }
  186. return !info.IsDir()
  187. }
  188. // GetFileAsString - returns the string contents of a given file
  189. func GetFileAsString(path string) (string, error) {
  190. content, err := os.ReadFile(path)
  191. if err != nil {
  192. return "", err
  193. }
  194. return string(content), err
  195. }
  196. // RunCmd - runs a local command
  197. func RunCmd(command string, printerr bool) (string, error) {
  198. args := strings.Fields(command)
  199. cmd := exec.Command(args[0], args[1:]...)
  200. cmd.Wait()
  201. out, err := cmd.CombinedOutput()
  202. if err != nil && printerr {
  203. log.Println("error running command: ", command)
  204. log.Println(strings.TrimSuffix(string(out), "\n"))
  205. }
  206. return string(out), err
  207. }
  208. // RemovePeer removes a Wireguard Peer from the interface iface
  209. func (w *WGIface) RemovePeer(peerKey string) error {
  210. w.mu.Lock()
  211. defer w.mu.Unlock()
  212. log.Printf("Removing peer %s from interface %s ", peerKey, w.Name)
  213. peerKeyParsed, err := wgtypes.ParseKey(peerKey)
  214. if err != nil {
  215. return err
  216. }
  217. peer := wgtypes.PeerConfig{
  218. PublicKey: peerKeyParsed,
  219. Remove: true,
  220. }
  221. config := wgtypes.Config{
  222. Peers: []wgtypes.PeerConfig{peer},
  223. }
  224. err = w.configureDevice(config)
  225. if err != nil {
  226. return fmt.Errorf("received error \"%v\" while removing peer %s from interface %s", err, peerKey, w.Name)
  227. }
  228. return nil
  229. }
  230. // UpdatePeer
  231. func (w *WGIface) Update(peerConf wgtypes.PeerConfig, updateOnly bool) error {
  232. w.mu.Lock()
  233. defer w.mu.Unlock()
  234. var err error
  235. log.Printf("---------> NEWWWWWW Updating peer %+v from interface %s ", peerConf, w.Name)
  236. peerConf.UpdateOnly = updateOnly
  237. peerConf.ReplaceAllowedIPs = true
  238. config := wgtypes.Config{
  239. Peers: []wgtypes.PeerConfig{peerConf},
  240. }
  241. err = w.configureDevice(config)
  242. if err != nil {
  243. return fmt.Errorf("received error \"%v\" while Updating peer %s from interface %s", err, peerConf.PublicKey.String(), w.Name)
  244. }
  245. return nil
  246. }
  247. func GetPeer(ifaceName, peerPubKey string) (wgtypes.Peer, error) {
  248. wg, err := wgctrl.New()
  249. if err != nil {
  250. return wgtypes.Peer{}, err
  251. }
  252. defer func() {
  253. err = wg.Close()
  254. if err != nil {
  255. log.Printf("got error while closing wgctl: %v", err)
  256. }
  257. }()
  258. wgDevice, err := wg.Device(ifaceName)
  259. if err != nil {
  260. return wgtypes.Peer{}, err
  261. }
  262. for _, peer := range wgDevice.Peers {
  263. if peer.PublicKey.String() == peerPubKey {
  264. return peer, nil
  265. }
  266. }
  267. return wgtypes.Peer{}, fmt.Errorf("peer not found")
  268. }