wg.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  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) [32]byte {
  72. wgClient, err := wgctrl.New()
  73. if err != nil {
  74. log.Println("Error fetching pub key: ", iface, err)
  75. return [32]byte{}
  76. }
  77. dev, err := wgClient.Device(iface)
  78. if err != nil {
  79. log.Println("Error fetching pub key: ", iface, err)
  80. return [32]byte{}
  81. }
  82. return dev.PublicKey
  83. }
  84. func GetWgIfacePrivKey(iface string) [32]byte {
  85. wgClient, err := wgctrl.New()
  86. if err != nil {
  87. log.Println("Error fetching pub key: ", iface, err)
  88. return [32]byte{}
  89. }
  90. dev, err := wgClient.Device(iface)
  91. if err != nil {
  92. log.Println("Error fetching pub key: ", iface, err)
  93. return [32]byte{}
  94. }
  95. return dev.PrivateKey
  96. }
  97. // parseAddress parse a string ("1.2.3.4/24") address to WG Address
  98. func parseAddress(address string) (WGAddress, error) {
  99. ip, network, err := net.ParseCIDR(address)
  100. if err != nil {
  101. return WGAddress{}, err
  102. }
  103. return WGAddress{
  104. IP: ip,
  105. Network: network,
  106. }, nil
  107. }
  108. // UpdatePeer updates existing Wireguard Peer or creates a new one if doesn't exist
  109. func (w *WGIface) UpdatePeer(peerKey string, allowedIps []net.IPNet, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error {
  110. w.mu.Lock()
  111. defer w.mu.Unlock()
  112. log.Printf("updating interface %s peer %s: endpoint %s ", w.Name, peerKey, endpoint)
  113. // //parse allowed ips
  114. // _, ipNet, err := net.ParseCIDR(allowedIps)
  115. // if err != nil {
  116. // return err
  117. // }
  118. peerKeyParsed, err := wgtypes.ParseKey(peerKey)
  119. if err != nil {
  120. return err
  121. }
  122. peer := wgtypes.PeerConfig{
  123. PublicKey: peerKeyParsed,
  124. ReplaceAllowedIPs: true,
  125. AllowedIPs: allowedIps,
  126. PersistentKeepaliveInterval: &keepAlive,
  127. PresharedKey: preSharedKey,
  128. Endpoint: endpoint,
  129. }
  130. config := wgtypes.Config{
  131. Peers: []wgtypes.PeerConfig{peer},
  132. }
  133. err = w.configureDevice(config)
  134. if err != nil {
  135. 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())
  136. }
  137. return nil
  138. }
  139. // configureDevice configures the wireguard device
  140. func (w *WGIface) configureDevice(config wgtypes.Config) error {
  141. wg, err := wgctrl.New()
  142. if err != nil {
  143. return err
  144. }
  145. defer wg.Close()
  146. // validate if device with name exists
  147. _, err = wg.Device(w.Name)
  148. if err != nil {
  149. return err
  150. }
  151. log.Printf("got Wireguard device %s\n", w.Name)
  152. return wg.ConfigureDevice(w.Name, config)
  153. }
  154. // GetListenPort returns the listening port of the Wireguard endpoint
  155. func (w *WGIface) GetListenPort() (*int, error) {
  156. log.Printf("getting Wireguard listen port of interface %s", w.Name)
  157. //discover Wireguard current configuration
  158. wg, err := wgctrl.New()
  159. if err != nil {
  160. return nil, err
  161. }
  162. defer wg.Close()
  163. d, err := wg.Device(w.Name)
  164. if err != nil {
  165. return nil, err
  166. }
  167. log.Printf("got Wireguard device listen port %s, %d", w.Name, d.ListenPort)
  168. return &d.ListenPort, nil
  169. }
  170. // GetRealIface - retrieves tun iface based on reference iface name from config file
  171. func GetRealIface(iface string) (string, error) {
  172. RunCmd("wg show interfaces", false)
  173. ifacePath := "/var/run/wireguard/" + iface + ".name"
  174. if !(FileExists(ifacePath)) {
  175. return "", errors.New(ifacePath + " does not exist")
  176. }
  177. realIfaceName, err := GetFileAsString(ifacePath)
  178. if err != nil {
  179. return "", err
  180. }
  181. realIfaceName = strings.TrimSpace(realIfaceName)
  182. if !(FileExists(fmt.Sprintf("/var/run/wireguard/%s.sock", realIfaceName))) {
  183. return "", errors.New("interface file does not exist")
  184. }
  185. return realIfaceName, nil
  186. }
  187. // FileExists - checks if file exists locally
  188. func FileExists(f string) bool {
  189. info, err := os.Stat(f)
  190. if os.IsNotExist(err) {
  191. return false
  192. }
  193. if err != nil && strings.Contains(err.Error(), "not a directory") {
  194. return false
  195. }
  196. if err != nil {
  197. log.Println(0, "error reading file: "+f+", "+err.Error())
  198. }
  199. return !info.IsDir()
  200. }
  201. // GetFileAsString - returns the string contents of a given file
  202. func GetFileAsString(path string) (string, error) {
  203. content, err := os.ReadFile(path)
  204. if err != nil {
  205. return "", err
  206. }
  207. return string(content), err
  208. }
  209. // RunCmd - runs a local command
  210. func RunCmd(command string, printerr bool) (string, error) {
  211. args := strings.Fields(command)
  212. cmd := exec.Command(args[0], args[1:]...)
  213. cmd.Wait()
  214. out, err := cmd.CombinedOutput()
  215. if err != nil && printerr {
  216. log.Println("error running command: ", command)
  217. log.Println(strings.TrimSuffix(string(out), "\n"))
  218. }
  219. return string(out), err
  220. }
  221. // RemovePeer removes a Wireguard Peer from the interface iface
  222. func (w *WGIface) RemovePeer(peerKey string) error {
  223. w.mu.Lock()
  224. defer w.mu.Unlock()
  225. log.Printf("Removing peer %s from interface %s ", peerKey, w.Name)
  226. peerKeyParsed, err := wgtypes.ParseKey(peerKey)
  227. if err != nil {
  228. return err
  229. }
  230. peer := wgtypes.PeerConfig{
  231. PublicKey: peerKeyParsed,
  232. Remove: true,
  233. }
  234. config := wgtypes.Config{
  235. Peers: []wgtypes.PeerConfig{peer},
  236. }
  237. err = w.configureDevice(config)
  238. if err != nil {
  239. return fmt.Errorf("received error \"%v\" while removing peer %s from interface %s", err, peerKey, w.Name)
  240. }
  241. return nil
  242. }
  243. // UpdatePeer
  244. func (w *WGIface) Update(peerConf wgtypes.PeerConfig, updateOnly bool) error {
  245. w.mu.Lock()
  246. defer w.mu.Unlock()
  247. var err error
  248. log.Printf("---------> NEWWWWWW Updating peer %+v from interface %s ", peerConf, w.Name)
  249. peerConf.UpdateOnly = updateOnly
  250. peerConf.ReplaceAllowedIPs = true
  251. config := wgtypes.Config{
  252. Peers: []wgtypes.PeerConfig{peerConf},
  253. }
  254. err = w.configureDevice(config)
  255. if err != nil {
  256. return fmt.Errorf("received error \"%v\" while Updating peer %s from interface %s", err, peerConf.PublicKey.String(), w.Name)
  257. }
  258. return nil
  259. }
  260. func GetPeer(ifaceName, peerPubKey string) (wgtypes.Peer, error) {
  261. wg, err := wgctrl.New()
  262. if err != nil {
  263. return wgtypes.Peer{}, err
  264. }
  265. defer func() {
  266. err = wg.Close()
  267. if err != nil {
  268. log.Printf("got error while closing wgctl: %v", err)
  269. }
  270. }()
  271. wgDevice, err := wg.Device(ifaceName)
  272. if err != nil {
  273. return wgtypes.Peer{}, err
  274. }
  275. for _, peer := range wgDevice.Peers {
  276. if peer.PublicKey.String() == peerPubKey {
  277. return peer, nil
  278. }
  279. }
  280. return wgtypes.Peer{}, fmt.Errorf("peer not found")
  281. }