Updated the OpenOS vTunnel client, added pcap output to the vTunnel bridge.

This commit is contained in:
Izaya 2019-12-19 20:42:43 +11:00
parent 970926efb6
commit 11ec131ab8
3 changed files with 177 additions and 101 deletions

View File

@ -1,88 +1,142 @@
local vcomp = require "vcomponent" local vcomponent = require "vcomponent"
local serial = require "serialization"
local component = require "component" local component = require "component"
local computer = require "computer" local computer = require "computer"
local imt = require "interminitel"
local event = require "event" local event = require "event"
local internet = component.internet local imt = require "interminitel"
local addr, raddr = vcomp.uuid(),vcomp.uuid() local cfg = {}
local poll = 0.5 cfg.peers = {}
local listener, timer cfg.rtimer = 5
local socket cfg.katimer = 30
local listeners = {}
local timers = {}
local proxies = {}
-- dumb keepalive stuff local function loadcfg()
local keepalive = 30 local f = io.open("/etc/vtunnel.cfg","rb")
local katimer if not f then return false end
for k,v in pairs(serial.unserialize(f:read("*a")) or {}) do
function start(faddr) cfg[k] = v
if listener then return end
if faddr then
local host,nport = faddr:match("(.+):(%d+)")
end end
local iaddr,port = host or faddr or "shadowkat.net", tonumber(nport) or 4096 f:close()
socket = internet.connect(iaddr,port) end
print("Connecting to "..iaddr..":"..tostring(port).."...") local function savecfg()
repeat local f = io.open("/etc/vtunnel.cfg","wb")
os.sleep(0.5) if not f then
until socket.finishConnect() print("Warning: unable to save configuration.")
print("Connected!") return false
end
local proxy = {} f:write(serial.serialize(cfg))
local rbuffer = "" f:close()
local timer = nil end
function listener(t) local function createTunnel(host,port,addr,raddr)
rbuffer=rbuffer..(socket.read(4096) or "") local proxy = {address=addr,buffer=""}
if imt.decodePacket(rbuffer) then function proxy.connect()
computer.pushSignal("modem_message",addr,raddr,0,0,imt.decodePacket(rbuffer)) if proxy.socket then
rbuffer = imt.getRemainder(rbuffer) or "" proxy.socket.close()
end end
if t == "internet_ready" and timer then proxy.socket = component.internet.connect(host,port)
event.cancel(timer) local st = computer.uptime()
timer = nil repeat
end coroutine.yield()
until proxy.socket.finishConnect() or computer.uptime() > st+5
end end
timer = event.timer(poll,listener,math.huge) -- this is only here because OCEmu doesn't do internet_ready
event.listen("internet_ready",listener)
-- also dumb keepalive stuff, fix this later
katimer = event.timer(keepalive,function()
socket.write("\0\1\0")
end,math.huge)
function proxy.send(...) function proxy.send(...)
socket.write(imt.encodePacket(...)) rt = 0
while not proxy.socket.write(imt.encodePacket(...)) and rt < 10 do
proxy.connect()
rt = rt + 1
end
proxy.last = computer.uptime()
end end
function proxy.read()
function proxy.maxPacketSize() local rb, r
return 12288 local rt = 0
while true do
rb,r = proxy.socket.read(4096)
if rb or rt > 10 then break end
if type(rb) == "nil" then
proxy.connect()
end
rt = rt + 1
end
proxy.buffer = proxy.buffer .. rb
while imt.decodePacket(proxy.buffer) do
computer.pushSignal("modem_message",addr,raddr,0,0,imt.decodePacket(proxy.buffer))
proxy.buffer = imt.getRemainder(proxy.buffer) or ""
end
if computer.uptime() > proxy.last + cfg.katimer then
proxy.socket.write("\0\1\0")
proxy.last = computer.uptime()
end
end end
event.listen("internet_ready",proxy.read)
proxy.type = "tunnel" listeners[addr] = {"internet_ready",proxy.read}
proxy.slot = 4096 timers[addr] = event.timer(cfg.rtimer, proxy.read, math.huge)
proxy.connect()
local docs = { proxy.last = computer.uptime()
send = "function(data...) -- Sends the specified data to the card this one is linked to.", return proxy
maxPacketSize = "function():number -- Gets the maximum packet size (config setting)."
}
vcomp.register(addr,"tunnel",proxy,docs)
end end
function stop() function start()
if listener then loadcfg()
event.ignore("internet_ready",listener) for k,v in pairs(cfg.peers) do
listener = nil print(string.format("Connecting to %s:%d",v.host,v.port))
v.addr = v.addr or vcomponent.uuid()
v.raddr = v.raddr or vcomponent.uuid()
local px = createTunnel(v.host, v.port, v.addr, v.raddr)
vcomponent.register(v.addr, "tunnel", px)
proxies[v.addr] = px
end end
if timer then end
event.cancel(timer) function stop()
timer = nil for k,v in pairs(listeners) do
end event.ignore(v[1],v[2])
if katimer then end
event.cancel(katimer) for k,v in pairs(timers) do
katimer = nil event.cancel(v)
end end
if component.type(addr) then for k,v in pairs(proxies) do
vcomp.unregister(addr) vcomponent.unregister(k)
end end
socket.close() end
function settimer(time)
time = tonumber(time)
if not time then
print("Timer must be a number.")
return false
end
cfg.rtime = time
savecfg()
end
function addpeer(host,port)
port = tonumber(port) or 4096
local t = {}
t.host = host
t.port = port
t.addr = vcomponent.uuid()
t.raddr = vcomponent.uuid()
cfg.peers[#cfg.peers+1] = t
print(string.format("Added peer #%d (%s:%d) to the configuration.\nRestart to apply changes.",#cfg.peers,host,port))
savecfg()
end
function listpeers()
for k,v in pairs(cfg.peers) do
print(string.format("#%d (%s:%d)\n Local address: %s\n Remote address: %s",k,v.host,v.port,v.addr,v.raddr))
end
end
function delpeer(n)
n=tonumber(n)
if not n then
print("delpeer requires a number, representing the peer number, as an argument.")
return false
end
local dp = table.remove(cfg.peers, n)
savecfg()
print(string.format("Removed peer %s:%d",dp.host, dp.port))
end end

View File

@ -8,23 +8,13 @@ The protocol is documented [here](vtunnel-protocol.md)
## Setup ## Setup
### Server ### Server Requirements
#### Requirements
- Some form of unix-like - Some form of unix-like
- Lua 5.2 or 5.3 - Lua 5.2 or 5.3
- Luasocket - Luasocket
#### Running the server ### Client Installation
At present, all you need to do is run bridge.lua, for example:
```
lua53 bridge.lua [port] [timeout]
```
### Client
#### OPPM #### OPPM
@ -37,33 +27,46 @@ oppm install vtunnel
1. Install vtunnel.lua to /etc/rc.d 1. Install vtunnel.lua to /etc/rc.d
2. Install interminitel.lua to /usr/lib 2. Install interminitel.lua to /usr/lib
#### Running ### Client setup
#### Creating a connection
Many connections can be configured. To add one:
```
rc vtunnel addpeer <server address> <server port>
```
## Usage
### Running the server
At present, all you need to do is run bridge.lua, for example:
```
lua53 bridge.lua [port] [timeout]
```
### Client
vTunnel is invoked as follows: vTunnel is invoked as follows:
``` ```
rc vtunnel start <server address>:<server port> rc vtunnel start
``` ```
This will create a virtual linked card component connected to server\_address:server\_port. vTunnel can also be configured to start automatically:
#### Configuration
vTunnel can also be configured to start automatically. First, one would enable the rc service:
``` ```
rc vtunnel enable rc vtunnel enable
``` ```
Then, edit /etc/rc.cfg and add a line as follows: There are several other commands available under `rc vtunnel`:
``` - settimer - allows you to configure how often vTunnel polls the TCP socket
vtunnel = "server.address:port" - listpeers - shows which peers are configured, and the associated tunnel card addresses
``` - delpeer - deletes a peer from the configuration, as shown in listpeers
Leaving it as default will result in vTunnel connecting to the public SKS bridge. ### Minitel configuration
#### Minitel configuration
1. Disable minitel with rc - `rc minitel disable` 1. Disable minitel with rc - `rc minitel disable`
2. Enable vtunnel with rc - `rc vtunnel enable` 2. Enable vtunnel with rc - `rc vtunnel enable`

View File

@ -1,9 +1,10 @@
local socket = require "socket" local socket = require "socket"
local imt = require "interminitel" local imt = require "interminitel"
local pcap = require "pcap"
local tArgs = {...} local tArgs = {...}
local port, timeout = tonumber(tArgs[1]) or 4096, tonumber(tArgs[2]) or 60 local port, timeout, pf = tonumber(tArgs[1]) or 4096, tonumber(tArgs[2]) or 60, tArgs[3]
local clients, coroutines, messages = {}, {}, {} local clients, coroutines, messages = {}, {}, {}
@ -101,6 +102,14 @@ function pushLoop()
reprint("Message #"..tostring(id).." (Client #"..tostring(msg[2]).." -> Client #"..tostring(k)..") - "..msg[1]) reprint("Message #"..tostring(id).." (Client #"..tostring(msg[2]).." -> Client #"..tostring(k)..") - "..msg[1])
end end
end end
if pf then
local f=io.open(pf,"ab")
if f then
f:write(pcap.packet(msg[1]))
print(pcap.packet(msg[1]))
f:close()
end
end
end end
messages[id] = nil messages[id] = nil
end end
@ -126,6 +135,16 @@ end
spawn(bufferLoop) spawn(bufferLoop)
if pf then
local f=io.open(pf,"wb")
if f then
f:write(pcap.header())
f:close()
else
pf=nil
end
end
while #coroutines > 0 do while #coroutines > 0 do
for k,v in pairs(coroutines) do for k,v in pairs(coroutines) do
coroutine.resume(v) coroutine.resume(v)