Thank you @LostKobrakai !!
I solved this togetherwith my coleage @uhrovat
In order to have this as refence I will try to write this in a way that I wish would have this before.
So the usecase is this. I have a Nerves based devices out in the field, connected over closed LTE network. So I can’t really reach devices from my cloud base service or directly from my dev laptop. Though majority of features is supported/implemented with the use of MQTT calls between device and cloud, there is still a great feeling being able to jump on a device and do some system checks or maintenance. In my case latter as I will be dealing with custom data handling and processin solution.
OPENSSH way (tested without nerves on clasic linux box)
1.) I crated ssh reverse tunnel with this on boxA (like gateway on picture)
ssh -i /home/tomaz/.ssh/nemo/user_ssh_key -nN -R 2222:localhost:22 Auser@192.168.x.130
user_ssh_key is a key on a proxy server, and Auser is a user on sshproxy server
2.) On ssh proxy I only added
3.) On my laptop I did
ssh -i gateway-id_rsa tomaz@192.168.x.130 -p 2222
gateway-id_rsa is a key that resolves against the PKI on gateway, and tomaz is a user on gateway.
With this in place I gain access to the “TERMINAL” shell on my boxA - which kind of simulates a real nerves gateway on picture. I do think this is really importnat for later
.
:SSH (Erlang way). - still without real Nerves gateway.
I’ve created a reverse tunnel on linux VM box (not actual Nerves gateway)
:ssh
library expects file to be one of -> id_rsa, id_dsa or id_ecdsa
. ssh — ssh v5.2.3
I actually had to rename my key to be id_rsa
and not some random name even though I tried to point to it
:ok = :ssh.start()
user = ~c"Auser"
userdir = ~c"/home/tomaz/.ssh/nemo"
ssh_option = [{:user, user}, {:silently_accept_hosts, true}, {:user_interaction, false}, {:user_dir, userdir}]
{:ok, conn} = :ssh.connect(String.to_charlist("192.168.x.130"), 22, ssh_option)
:ssh.tcpip_tunnel_from_server(conn, String.to_charlist("192.168.6.130"), 3333, String.to_charlist("localhost"), 22)
And this setup did establish the ssh reverse proxy. I logged everything in /var/log/auth
on a sshproxy.
Then on my laptop I did
ssh -i Auser Auser@192.168.x.130 -p 3333
And with that I got access to linux shell (terminal) on the “gateway” linux VM box.
SSH (Erlang way) - NOW ON NERVES DEVICE
Similar approach as previous example but now on actual device.
iex(13)> :ssh.tcpip_tunnel_from_server(conn, String.to_charlist("mydomain"), 3333, String.to_charlist("localhost"), 22)
{:ok, 3334}
iex(14)>
Then from my dev laptop
ssh -i /Users/tomaz/.ssh/nemo/tomaz-id_rsa nerves@192.168.x.130 -p 3333
private key
has a public key on a gateway. User
is for gateway, and IP
is for sshproxy server.
And what I get is wooohooo!!!
Warning: Permanently added '[192.168.x.130]:3333' (ED25519) to the list of known hosts.
Interactive Elixir (1.17.3) - press Ctrl+C to exit (type h() ENTER for help)
████▄▄ ▐███
█▌ ▀▀██▄▄ ▐█
█▌ ▄▄ ▀▀ ▐█ N E R V E S
█▌ ▀▀██▄▄ ▐█
███▌ ▀▀████
nemo 0.26.0 (0626c4d3-89d7-5e8d-0584-d8f685366269) arm rpi4
Serial : 1000000094278b35
Uptime : 2 hours, 44 minutes and 16 seconds
Clock : 2024-11-15 12:16:21 UTC
Temperature : 29.7°C
Firmware : Valid (B) Applications : 62 started (nemo not started)
Memory usage : 163 MB (4%) Part usage : 493 MB (2%)
Hostname : nerves-8b35 Load average : 0.00 0.00 0.00
eth0 : 192.168.x.163/24, fe80::da3a:ddff:feab:daf2/64
Nerves CLI help: https://hexdocs.pm/nerves/iex-with-nerves.html
Toolshed imported. Run h(Toolshed) for more info.
iex(1)>
currently my gateway is connected with ethernet cable, since my LTE doesn’t have a signal here.
Huge thumbs up to @uhrovat for joining efforts.
Hope this post helps others in the future.