How to configure wg0 interface on Windows 10? - go

I am not able to manage the wireguard interface using wgctl on Windows (10). I have used it on linux and all is fine. I'm using Windows 10 latest updates, wireguard.exe latest, go 1.17.3 latest.
I am using a tunnel created with wireguard.exe /installtunnelservice /path/wg0.conf. If I manage the tunnel with the wireguard GUI, it all works fine. But I need to do it programatically.
C:\>wg
interface: wg0
public key: K0BZ3Bk...5tCWo=
private key: (hidden)
listening port: 57538
peer: 7W6tOXI...F7zAo=
endpoint: 159....105:51820
allowed ips: 100.127.128.0/18
latest handshake: 43 seconds ago
transfer: 31.61 KiB received, 115.69 KiB sent
persistent keepalive: every 25 seconds
...
The following code exits with "file does not exist". Having stepped the code into the library, I think that wireguard.exe is using NT Kernel mode and the library does not support it? Can someone please confirm? What is the best way around this?
package main
import (
"log"
"golang.zx2c4.com/wireguard/wgctrl"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
)
func main() {
wgc, err := wgctrl.New()
if err != nil {
log.Printf("wgctrl.New: %s", err)
}
defer wgc.Close()
cfg := wgtypes.Config{}
port := 51822
cfg.ListenPort = &port
err = wgc.ConfigureDevice("wg0", cfg)
if err != nil {
log.Printf("wgc.ConfigureDevice: %s", err)
}
}

After escalating the issue on GitHub, it turned out to be a bug in the library which was promptly fixed not long after I posted this.

Related

Why does Go send my multicast packet only using loopback interface?

I can not send multicast request to LAN from Go on Win10.
I have Windows 10 1909.
I am running wireshark with filter host 239.255.255.250 or host 172.19.21.116 or port 1982 where .116 is IP of device I am looking for.
I have YeeLight UWP app installed
I have this code (removed every if err != nil):
package main
import (
"bytes"
"net"
"time"
)
func main() {
bulbMulticastAddr := &net.UDPAddr{IP: net.IPv4(239, 255, 255, 250), Port: 1982}
bulbSearchRequest := new(bytes.Buffer)
_, err := bulbSearchRequest.WriteString("M-SEARCH * HTTP/1.1\r\nHOST:239.255.255.250:1982\r\nMAN:\"ssdp:discover\"\r\nST:wifi_bulb\r\n")
conn, err := net.ListenUDP("udp4", bulbMulticastAddr)
conn.WriteTo(bulbSearchRequest.Bytes(), bulbMulticastAddr)
time.Sleep(time.Duration(6) * time.Second)
}
When I run go run myapp, in WireShark I see single UDP packet with source 127.0.0.1 and destination 239.255.255.250
When I run Yeelight UWP app, in WireShark I see in WireShark two same packets: one using Ethernet interface and one using loopback.
And after some time OS works (few hours - different apps are running), it starts working.
When I use
iflist, _ := net.Interfaces() // iflist[0] is Ethernet
conn, err := net.ListenMulticastUDP("udp4", &iflist[0], bulbMulticastAddr)
conn.WriteTo(bulbSearchRequest.Bytes(), bulbMulticastAddr)
Everything goes right
What am I doing wrong? Each tutorial about multicast shows the way I am doing is right, but it does not work as expected. I am missing something?
Why ListenUDP() not working as expected?
go version go1.14 windows/amd64

One page REST api on go server to return system MAC address

I have a PHP based web application. On the login page, it makes an AJAX call to a Go server (located on the client machine) to get its MAC address. Below is the Go server code:
package main
import (
"net"
"net/http"
"encoding/json"
)
//define struct for mac address json
type MacAddress struct {
Id string
}
/**
* Get device mac address
*/
func GetMacAddress(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
mac := &MacAddress{Id: ""}
ifas, err := net.Interfaces()
if err != nil {
json.NewEncoder(w).Encode(mac)
return
}
for _, ifa := range ifas {
a := ifa.HardwareAddr.String()
if a != "" {
mac := &MacAddress{Id: a}
json.NewEncoder(w).Encode(mac)
break
}
}
return
}
/**
* Main function
*/
func main() {
http.HandleFunc("/", GetMacAddress)
if err := http.ListenAndServe(":8000", nil); err != nil {
panic(err)
}
}
Result:
{Id: "8c:16:45:5h:1e:0e"}
Here I have 2 questions.
Sometimes i get the error
panic: listen tcp :8000: bind: address already in use
and I manually kill the process. So, what can be improved in my code to avoid this error and close the previously running server?
Can a stand-alone, compiled Go file (created on ubuntu) be run on other systems like windows or linux or mac without having all Go libs and setup?
Information on how to cross-compile a Go program for different operation systems can be found here. Briefly, instead of running go build main.go, run:
env GOARCH=amd64 GOOS=<target_OS> CGO_ENABLED=1 go build -v main.go
I usually have a Makefile to simplify the process of cross-compiling for linux, windows, and macOS.
With regard to your second question, I can only reproduce your error on my machine when I try to ListenAndServe twice. I.e. I suspect that during your debugging cycles, you forgot to close a running server while trying to start a new instance in another terminal window. Make sure to abort your Go program with ctrl + c before running it again.

Can't connect to tcp server more than 140 connections?

I am building a tcp socket server in golang. It works well with less than ~140 client connection. But if i try to set max connection number to 500, after 140th clients do not connect to the server.
I increased file descriptor count to 1048576 but it does not still work.
$ulimit -n
1048576
I think the problem comes from operation system.(server and clients work on same machine) So OS information:
Mac OS 10.12 Sierra 64 bit.
Does anyone have any idea why i can't increase tcp connection number?
github
I am on the same operating system as you, but I could not reproduce your issue. I am using Go version 1.7.4. I have not tested on Go 1.8, but it was released earlier today.
I created two files, server.go and client.go (reproduced below). When I run them, I get way more than 140 connections. Before running, I switched to root and setup the ulimit like so:
$ sudo -s
$ ulimit -n 10000
The client outputs:
Established 1 connections
...
Established 2971 connections
panic: dial tcp 127.0.0.1:1337: socket: too many open files in system
The server outputs something very similar.
Here is client.go:
package main
import (
"fmt"
"net"
)
func main() {
var numConns int
for {
_, err := net.Dial("tcp", "127.0.0.1:1337")
if err != nil {
panic(err)
}
numConns++
fmt.Println("Established", numConns, "connections")
}
}
And server.go:
package main
import (
"fmt"
"net"
)
func main() {
listener, err := net.Listen("tcp", ":1337")
if err != nil {
panic(err)
}
var numConns int
for {
_, err := listener.Accept()
if err != nil {
panic(err)
}
numConns++
fmt.Println("Got", numConns, "connections")
}
}
This is not a problem with the operating system, but the hardware. It is likely a problem with your router. Commercial routers do tend to fail when you get into that range. My guess is that Alex is testing at a large company or university where they have commercial grade routers, but you are testing at home.

How to ping an IP Address in golang

How can you ping an IP address from a golang application? The ultimate goal is to check if a server is online.
Does go have a way in the standard library to implement a network ping?
As #desaipath mentions, there is no way to do this in the standard library. However, you do not need to write the code for yourself - it has already been done:
https://github.com/tatsushid/go-fastping
Note, sending ICMP packets requires root privileges
I needed the same thing as you and I've made a workaround (with exec.Command) for my Raspberry Pi to check if servers are online. Here is the experimental code
out, _ := exec.Command("ping", "192.168.0.111", "-c 5", "-i 3", "-w 10").Output()
if strings.Contains(string(out), "Destination Host Unreachable") {
fmt.Println("TANGO DOWN")
} else {
fmt.Println("IT'S ALIVEEE")
}
#jpillora's answer suggests using go-fastping, but that library hasn't been updated since Jan 8, 2016. It may not be an issue as the logic of pinging is quite simple, but if you want a more recent package then there's go-ping.
Although not a real ICMP ping, this is what use to probe my servers using the TCP protocol:
host := "example.com"
port := "80"
timeout := time.Duration(1 * time.Second)
_, err := net.DialTimeout("tcp", host+":"+port, timeout)
if err != nil {
fmt.Printf("%s %s %s\n", host, "not responding", err.Error())
} else {
fmt.Printf("%s %s %s\n", host, "responding on port:", port)
}
No.
Go does not have any built-in way to ping a server in standard library.
You need to write code by yourself.
For that, you can look into icmp section of golang library. And use this list of control messages, to construct icmp message properly.
But, keep in mind that some server administrator shuts down ping service on their server, for security reason. So, If your goal is to ultimately check if server is online or not, this is not 100% reliable method.
package main
import (
"fmt"
"os/exec"
)
func main() {
Command := fmt.Sprintf("ping -c 1 10.2.201.174 > /dev/null && echo true || echo false")
output, err := exec.Command("/bin/sh", "-c", Command).Output()
fmt.Print(string(output))
fmt.Print(err)
}

Simple SSH port forward in Golang

I'm trying to create (and later close) a simple TCP port forward over SSH with Go. I'm new to Golang and statically typed languages. (Coming from Ruby.)
In a terminal I would simply run ssh -L 9000:localhost:9999 user#server.com and this accomplishes what I need. I want to do the same, programmatically with Go.
I have tried using this example as a starting point and this recent test to try to understand what to do, but now I have a pile of confusing jumbled code when it seems like this is actually a very simple thing to do.
Any help would be very much appreciated! :-)
I finally figured out how to do this, I got hints from schmichael in an IRC channel. Thanks to all!
EDIT: A little explanation:
A big part of the problem I was having was that I did not realize a local net.Listener (not just a local net.Conn) needed setup to receive a local request and create the net.Conn before forwarding the bytes.
Also, there exist both port forwards and reverse port forwards and I hadn't previously thought in detail about the fact that a regular port forward also sends bytes back, so copying the remote reader to local writer was not something I had implemented, yet it's very much needed.
Here is an attempt to relate the essence of what this code does:
Listen on local port 9000.
Upon attempted read from local port 9000: (listener.Accept()),
Accept connection and return a local io.Reader and io.Writer and,
Connect to remote server and,
Connect to remote port 9999 returning a io.Reader and io.Writer.
Continually copy local io.Reader bytes to remote io.Writer,
Continually copy remote io.Reader bytes to local io.Writer.
Here is the code:
package main
// Forward from local port 9000 to remote port 9999
import (
"io"
"log"
"net"
"golang.org/x/crypto/ssh"
)
var (
username = "root"
password = "password"
serverAddrString = "192.168.1.100:22"
localAddrString = "localhost:9000"
remoteAddrString = "localhost:9999"
)
func forward(localConn net.Conn, config *ssh.ClientConfig) {
// Setup sshClientConn (type *ssh.ClientConn)
sshClientConn, err := ssh.Dial("tcp", serverAddrString, config)
if err != nil {
log.Fatalf("ssh.Dial failed: %s", err)
}
// Setup sshConn (type net.Conn)
sshConn, err := sshClientConn.Dial("tcp", remoteAddrString)
// Copy localConn.Reader to sshConn.Writer
go func() {
_, err = io.Copy(sshConn, localConn)
if err != nil {
log.Fatalf("io.Copy failed: %v", err)
}
}()
// Copy sshConn.Reader to localConn.Writer
go func() {
_, err = io.Copy(localConn, sshConn)
if err != nil {
log.Fatalf("io.Copy failed: %v", err)
}
}()
}
func main() {
// Setup SSH config (type *ssh.ClientConfig)
config := &ssh.ClientConfig{
User: username,
Auth: []ssh.AuthMethod{
ssh.Password(password),
},
}
// Setup localListener (type net.Listener)
localListener, err := net.Listen("tcp", localAddrString)
if err != nil {
log.Fatalf("net.Listen failed: %v", err)
}
for {
// Setup localConn (type net.Conn)
localConn, err := localListener.Accept()
if err != nil {
log.Fatalf("listen.Accept failed: %v", err)
}
go forward(localConn, config)
}
}
I have used your (damick) example code to build a tiny open source tool: SSHTunnel
https://github.com/SommerEngineering/SSHTunnel
Therefore, the code is freely available at GitHub for anyone: Please feel free to use it for learning purposes or for anything else :) I have mentioned your nickname and also linked to this question.
Best regards,
Thorsten.
I'v finished a simple SSH port forward tool called mallory.
It provides HTTP proxy instead of SOCKS proxy, which is really similar to ssh -D.
The core code is similar to damick's answer.
Create ClientConfig
ssh.Dial to remote SSH server with the config and return Client
Now you can use Client.Dial to forward anything you like.
Dial initiates a connection to the addr from the remote host. The resulting connection has a zero LocalAddr() and RemoteAddr().
If you want to serve a SOCKS proxy server, use Client.Dial to connect to the remote server.
I Wrote a tool,Called gosshtool,with this tool,you can easy to create a simple TCP port forward over SSH with Go.https://github.com/scottkiss/gosshtool
I use this tool implemented a port forward server example project:
https://github.com/scottkiss/gooverssh

Resources