Skip to content

Commit

Permalink
feat: Use loopback (#26)
Browse files Browse the repository at this point in the history
When using ports instead of sockets, the Neovim port (both remote and
client) are bound to the loopback address, rather than `0.0.0.0`. This
should be a little more secure.

Ports tunneled via `NvrhTunnelPort` are still bound to `0.0.0.0` on the
client machine, that's because I still need to use my phone / tablet to
check things out sometimes, and if they were bound to `127.0.0.1` I
wouldn't be able to connect. Ideally, this would be configurable at
mapping-time, something like `NvrhTunnelPort 3000 interface=all` /
`NvrhTunnelPort 3000 interface=loopback`

- Clean up local socket
- Clean up remote socket
- Clean up remote browser script
- Use `filepath.Join` instead of `path.Join`
- Extract logger setup
  • Loading branch information
mikew authored Oct 21, 2024
1 parent 80b1686 commit d5abb3a
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 39 deletions.
50 changes: 16 additions & 34 deletions src/client/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import (
"os"
"os/exec"
"os/signal"
"path"
"path/filepath"
"runtime"
"strings"
"time"

"github.com/dusted-go/logging/prettylog"
"github.com/neovim/go-client/nvim"
"github.com/urfave/cli/v2"

"nvrh/src/context"
"nvrh/src/logger"
"nvrh/src/nvim_helpers"
"nvrh/src/ssh_helpers"
)
Expand Down Expand Up @@ -78,9 +78,12 @@ var CliClientOpenCommand = cli.Command{
},

Action: func(c *cli.Context) error {
isDebug := c.Bool("debug")
logger.PrepareLogger(isDebug)

// Prepare the context.
sessionId := fmt.Sprintf("%d", time.Now().Unix())
nvrhContext := context.NvrhContext{
nvrhContext := &context.NvrhContext{
SessionId: sessionId,
Server: c.Args().Get(0),
RemoteDirectory: c.Args().Get(1),
Expand All @@ -91,28 +94,13 @@ var CliClientOpenCommand = cli.Command{
ShouldUsePorts: c.Bool("use-ports"),

RemoteSocketPath: fmt.Sprintf("/tmp/nvrh-socket-%s", sessionId),
LocalSocketPath: path.Join(os.TempDir(), fmt.Sprintf("nvrh-socket-%s", sessionId)),
LocalSocketPath: filepath.Join(os.TempDir(), fmt.Sprintf("nvrh-socket-%s", sessionId)),

BrowserScriptPath: fmt.Sprintf("/tmp/nvrh-browser-%s", sessionId),

SshPath: c.String("ssh-path"),
Debug: c.Bool("debug"),
}

// Prepare the logger.
logLevel := slog.LevelInfo
if nvrhContext.Debug {
logLevel = slog.LevelDebug
Debug: isDebug,
}
log := slog.New(prettylog.New(
&slog.HandlerOptions{
Level: logLevel,
AddSource: nvrhContext.Debug,
},
prettylog.WithDestinationWriter(os.Stderr),
prettylog.WithColor(),
))
slog.SetDefault(log)

if nvrhContext.ShouldUsePorts {
min := 1025
Expand All @@ -133,7 +121,7 @@ var CliClientOpenCommand = cli.Command{

// Prepare remote instance.
go func() {
remoteCmd := ssh_helpers.BuildRemoteNvimCmd(&nvrhContext)
remoteCmd := ssh_helpers.BuildRemoteNvimCmd(nvrhContext)
if nvrhContext.Debug {
remoteCmd.Stdout = os.Stdout
remoteCmd.Stderr = os.Stderr
Expand Down Expand Up @@ -161,7 +149,7 @@ var CliClientOpenCommand = cli.Command{
// Prepare client instance.
nvChan := make(chan *nvim.Nvim, 1)
go func() {
nv, err := nvim_helpers.WaitForNvim(&nvrhContext)
nv, err := nvim_helpers.WaitForNvim(nvrhContext)

if err != nil {
slog.Error("Error connecting to nvim", "err", err)
Expand All @@ -171,11 +159,11 @@ var CliClientOpenCommand = cli.Command{
slog.Info("Connected to nvim")
nvChan <- nv

if err := prepareRemoteNvim(&nvrhContext, nv); err != nil {
slog.Error("Error preparing remote nvim", "err", err)
if err := prepareRemoteNvim(nvrhContext, nv); err != nil {
slog.Warn("Error preparing remote nvim", "err", err)
}

clientCmd := BuildClientNvimCmd(&nvrhContext)
clientCmd := BuildClientNvimCmd(nvrhContext)
if nvrhContext.Debug {
clientCmd.Stdout = os.Stdout
clientCmd.Stderr = os.Stderr
Expand Down Expand Up @@ -214,6 +202,7 @@ var CliClientOpenCommand = cli.Command{
slog.Info("Closing nvrh")
closeNvimSocket(nv)
killAllCmds(nvrhContext.CommandsToKill)
os.Remove(nvrhContext.LocalSocketPath)

if err != nil {
return err
Expand Down Expand Up @@ -253,8 +242,6 @@ func prepareRemoteNvim(nvrhContext *context.NvrhContext, nv *nvim.Nvim) error {
batch.Command(fmt.Sprintf(`let $BROWSER="%s"`, nvrhContext.BrowserScriptPath))

// Add command to tunnel port.
// TODO use `vim.api.nvim_create_user_command`, and check to see if the
// port is already mapped somehow.
batch.ExecLua(`
vim.api.nvim_create_user_command(
'NvrhTunnelPort',
Expand Down Expand Up @@ -303,11 +290,6 @@ os.execute('chmod +x ' .. browser_script_path)
return true
`, nil, nvrhContext.BrowserScriptPath, nvrhContext.RemoteSocketOrPort(), nv.ChannelID())






if err := batch.Execute(); err != nil {
return err
}
Expand Down Expand Up @@ -342,7 +324,7 @@ func killAllCmds(cmds []*exec.Cmd) {
slog.Debug("Killing command", "cmd", cmd.Args)
if cmd.Process != nil {
if err := cmd.Process.Kill(); err != nil {
slog.Error("Error killing command", "err", err)
slog.Warn("Error killing command", "err", err)
}
}
}
Expand All @@ -355,7 +337,7 @@ func closeNvimSocket(nv *nvim.Nvim) {

slog.Info("Closing nvim")
if err := nv.ExecLua("vim.cmd('qall!')", nil, nil); err != nil {
slog.Error("Error closing remote nvim", "err", err)
slog.Warn("Error closing remote nvim", "err", err)
}
nv.Close()
}
6 changes: 3 additions & 3 deletions src/context/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type NvrhContext struct {
Debug bool
}

func (nc NvrhContext) LocalSocketOrPort() string {
func (nc *NvrhContext) LocalSocketOrPort() string {
if nc.ShouldUsePorts {
// nvim-qt, at least on Windows (and might have something to do with
// running in a VM) seems to prefer `127.0.0.1` to `0.0.0.0`, and I think
Expand All @@ -37,9 +37,9 @@ func (nc NvrhContext) LocalSocketOrPort() string {
return nc.LocalSocketPath
}

func (nc NvrhContext) RemoteSocketOrPort() string {
func (nc *NvrhContext) RemoteSocketOrPort() string {
if nc.ShouldUsePorts {
return fmt.Sprintf("0.0.0.0:%d", nc.PortNumber)
return fmt.Sprintf("127.0.0.1:%d", nc.PortNumber)
}

return nc.RemoteSocketPath
Expand Down
27 changes: 27 additions & 0 deletions src/logger/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package logger

import (
"log/slog"
"os"

"github.com/dusted-go/logging/prettylog"
)

func PrepareLogger(isDebug bool) {
logLevel := slog.LevelInfo

if isDebug {
logLevel = slog.LevelDebug
}

log := slog.New(prettylog.New(
&slog.HandlerOptions{
Level: logLevel,
AddSource: isDebug,
},
prettylog.WithDestinationWriter(os.Stderr),
prettylog.WithColor(),
))

slog.SetDefault(log)
}
7 changes: 5 additions & 2 deletions src/ssh_helpers/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func BuildRemoteNvimCmd(nvrhContext *context.NvrhContext) *exec.Cmd {

tunnel := fmt.Sprintf("%s:%s", nvrhContext.LocalSocketPath, nvrhContext.RemoteSocketPath)
if nvrhContext.ShouldUsePorts {
tunnel = fmt.Sprintf("%d:0.0.0.0:%d", nvrhContext.PortNumber, nvrhContext.PortNumber)
tunnel = fmt.Sprintf("%d:127.0.0.1:%d", nvrhContext.PortNumber, nvrhContext.PortNumber)
}

sshCommand := exec.Command(
Expand Down Expand Up @@ -55,10 +55,13 @@ func buildRemoteCommandString(nvrhContext *context.NvrhContext) string {
}

return fmt.Sprintf(
"%s nvim --headless --listen \"%s\" --cmd \"cd %s\"",
"%s nvim --headless --listen \"%s\" --cmd \"cd %s\"; rm -f \"%s\"; [ %t = true ] && rm -f \"%s\"",
envPairsString,
nvrhContext.RemoteSocketOrPort(),
nvrhContext.RemoteDirectory,
nvrhContext.BrowserScriptPath,
!nvrhContext.ShouldUsePorts,
nvrhContext.RemoteSocketPath,
)
}

Expand Down

0 comments on commit d5abb3a

Please sign in to comment.