New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autossh plugin for OPNsense #818

Open
wants to merge 2 commits into
base: master
from

Conversation

Projects
None yet
4 participants
@ndejong

ndejong commented Sep 5, 2018

This PR implements a UI for the autossh package thus providing the ability to create and persist SSH tunnels from the OPNsense system to remote systems.

Features

  • Default ssh-key permissions that prevent unwanted remote ssh-server shell access abuses.
  • Ability to define local-forward and remote-forward TCP tunnels.
  • Ability to define local network SOCKS proxy via a remote host (aka dynamic-forward).
  • Ability to bind outbound ssh connections to different (external) interfaces.
  • Ability to configure many (27x) of the ssh-client connection parameters, including all cryptographic options.
  • Ability to observe the health status of the tunnel at a glance.
  • Can rely on Autossh to reestablish a tunnel after a connectivity outage.

Various use cases

  • Provide remote network access to a site that has no public addresses, such as when ISPs use NAT.
  • Ensure redundant multipath remote access via primary and secondary connections via interface binding.
  • Create your own "privacy" VPN system for all local network users using a SOCKS proxy (dynamic-forward) to a remote system.
  • Provide local network access to remote system services such as a SMTP relay or another SSH service.
  • Provide remote system access to a local network services such as a database or RDP service.
  • Provide access remote system access to other remote network acting as a middle-man TCP-port connector.

Looking forward to feedback

@fabianfrz

Some stuff tried to not repeat myself

$response = array("status"=>"success", "data" => $model->isConfigChange(), "message"=>null);
}
return $response;

This comment has been minimized.

@fabianfrz

fabianfrz Sep 5, 2018

Member

The $response variable is not needed

This comment has been minimized.

@ndejong

ndejong Sep 11, 2018

Returning early has been applied in all controllers - it's an old habit

public function startAction()
{
$response = array('status'=>'fail', 'message' => 'Invalid request');

This comment has been minimized.

@fabianfrz

fabianfrz Sep 5, 2018

Member

Use the same spacing style

This comment has been minimized.

@ndejong
'local' => htmlspecialchars($tunnel['local_forward']),
'dynamic' => htmlspecialchars($tunnel['dynamic_forward']),
'remote' => htmlspecialchars($tunnel['remote_forward']),
'tunnel' => htmlspecialchars($tunnel['tunnel_device'])

This comment has been minimized.

@fabianfrz

fabianfrz Sep 5, 2018

Member

This is an api, not a html renderer. No escaping here. Especially because of this ugly hack:
opnsense/core#2672

Escaping must be done in the viewer - which is the js code of the frontend.

This comment has been minimized.

@ndejong

ndejong Sep 11, 2018

Yes, I'm aware of opnsense/core#2672 if you take a look at my TunnelsController I specifically have an afterExecuteRoute() function to be able to step outside it in a very limited case - even with me implementing this I guess it did not occur to me that using htmlspecialchars() here is in-fact double-escaping things - either way, resolved

$response['rows'][] = array(
'uuid' => $tunnel['uuid'],
'connection' => htmlspecialchars($connection),

This comment has been minimized.

@fabianfrz

fabianfrz Sep 5, 2018

Member

see prev

<id>tunnel.description</id>
<label>Description</label>
<type>text</type>
<help><![CDATA[Free form text field available to describe this connection if required.]]></help>

This comment has been minimized.

@fabianfrz

fabianfrz Sep 5, 2018

Member

No cdata needed

This comment has been minimized.

@ndejong

ndejong Sep 11, 2018

okay - CDATA removed from the fields where it is not needed

public function setConfigChangeOn()
{
touch($this->config_status_filename);
return true;

This comment has been minimized.

@fabianfrz

fabianfrz Sep 5, 2018

Member

Instead you can just return nothing

<div class="col-md-12">
<h1>Autossh</h1>
<p>
The Autossh plugin for OPNsense is a tool for establishing, maintaining and managing

This comment has been minimized.

@fabianfrz

fabianfrz Sep 5, 2018

Member

Needs translation.

},
code_wrap: function(column, row) {
if(row[column.id].length > 0) {
return '<code>' + row[column.id] + '</code>';

This comment has been minimized.

@fabianfrz

fabianfrz Sep 5, 2018

Member

This is one of the places, where you would have to escape if this issue would not exist.

This comment has been minimized.

@ndejong

ndejong Sep 11, 2018

This is an excellent catch

$logfile = '/var/log/autossh.log';
$logclog = true;
// $service_hook = 'autossh';

This comment has been minimized.

@fabianfrz

fabianfrz Sep 5, 2018

Member

Delete dead code

@ndejong

This comment has been minimized.

ndejong commented Sep 6, 2018

@fabianfrz super appreciate the rapid turn around on feedback here, it really impresses me about the OPNsense team - I'm going to be busy on another project for the next week and will not be able to address these in the same quick turn around

@mimugmail

Some small things. I like the idea of autossh. Normally I'd do this with OpenVPN but SSH as an alternative is also nice

PLUGIN_COMMENT= Create and automatically persist SSH based tunnels.
PLUGIN_MAINTAINER= contact@verbnetworks.com
PLUGIN_WWW= https://verbnetworks.com
PLUGIN_DEVEL= no

This comment has been minimized.

@mimugmail
@@ -0,0 +1,182 @@
#!/bin/sh

This comment has been minimized.

@mimugmail

mimugmail Sep 6, 2018

Member

Normally whene there's no init script it's called opnsense-xxx so there wont be a collision when a new script comes in future by pkg maintainer

This comment has been minimized.

@ndejong

ndejong Sep 11, 2018

Ahh - I recall wondering about this - thanks, and sorting it out now

This comment has been minimized.

@mimugmail

mimugmail Sep 11, 2018

Member

Also dont forget in rc.conf.d .. 👍

public function infoAction($uuid = null)
{
$ssh_key_restrictions = 'command="",no-agent-forwarding,no-pty,no-user-rc,no-X11-forwarding';

This comment has been minimized.

@mimugmail

mimugmail Sep 6, 2018

Member

This is listed in the volt, no idea if this is really necessary?

This comment has been minimized.

@ndejong

ndejong Sep 11, 2018

yes - displaying the ssh public key to the user in a manner that is designed to prevent other security accidents is a deliberate thing as there will be some that may not understand the potential flow on effects - anyone that wants to strip off the key restrictions ought to know what they are doing

This comment has been minimized.

@mimugmail

mimugmail Sep 11, 2018

Member

Ok, looked a bit strange in UI bit I didn't have a deeper look into it yet.

<id>key.type</id>
<label>Type</label>
<type>dropdown</type>
<help>Select the type of SSH key to be generated - can't be modified after the key has been generated.</help>

This comment has been minimized.

@mimugmail

mimugmail Sep 6, 2018

Member

cannot

<id>key.description</id>
<label>Description</label>
<type>text</type>
<help>Free form input to describe this sshkey (not parsed).</help>

This comment has been minimized.

@mimugmail

mimugmail Sep 6, 2018

Member

Here sshkey, below SSH key ..

<id>tunnel.user</id>
<label>User</label>
<type>text</type>
<help><![CDATA[Provide the connection username for this connection.]]></help>

This comment has been minimized.

@mimugmail

mimugmail Sep 6, 2018

Member

I'd remove the first connection

This comment has been minimized.

@ndejong

ndejong Sep 11, 2018

Sharp eyes 👍

</optionvalues>
</macs>
<port type="IntegerField">

This comment has been minimized.

@mimugmail

mimugmail Sep 6, 2018

Member

You could also use PortField, no validation or min/max required

This comment has been minimized.

@ndejong

ndejong Sep 11, 2018

Ahh cool - I did not know

<div class="alert alert-info hidden" role="alert" id="responseMsg"></div>
<div class="alert alert-info hidden" role="alert" id="applyChangesMessage">
<button class="btn btn-primary pull-right" id="btnApplyChanges" type="button"><b>{{ lang._('Apply changes') }}</b> <i id="btnApplyChangesProgress"></i></button>

This comment has been minimized.

@mimugmail

mimugmail Sep 6, 2018

Member

This reminds me of legacy code how to apply changes, searched some time after I found the button :)

This comment has been minimized.

@ndejong

ndejong Sep 11, 2018

I took this approach because I could not see a better way to handle it

The underlying thing driving this is the need to call a helper script to correctly render the required ssh_config files because as best as I can tell I am not able to get what I need with Jinja alone - go looking for AutosshConfigHelper.py if you are interested

@mimugmail

This comment has been minimized.

Member

mimugmail commented Sep 6, 2018

Found this in system.log:

Sep  6 10:00:11 OPNsense /usr/local/bin/ssh[32527]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:00:11 OPNsense /usr/local/bin/ssh[32626]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:00:11 OPNsense /usr/local/bin/ssh[32684]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:00:12 OPNsense /usr/local/bin/ssh[32826]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:00:15 OPNsense /usr/local/bin/ssh[32956]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:00:20 OPNsense /usr/local/bin/ssh[33204]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:00:27 OPNsense /usr/local/bin/ssh[33458]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:00:36 OPNsense /usr/local/bin/ssh[46289]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:00:48 OPNsense /usr/local/bin/ssh[46474]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:01:05 OPNsense /usr/local/bin/ssh[48934]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:01:13 OPNsense /usr/local/bin/ssh[50763]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:01:13 OPNsense /usr/local/bin/ssh[50821]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:01:13 OPNsense /usr/local/bin/ssh[50925]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:01:13 OPNsense /usr/local/bin/ssh[51050]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:01:13 OPNsense /usr/local/bin/ssh[51240]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:01:13 OPNsense /usr/local/bin/ssh[51255]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:01:13 OPNsense /usr/local/bin/ssh[51313]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:01:13 OPNsense /usr/local/bin/ssh[51635]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.
Sep  6 10:01:14 OPNsense /usr/local/bin/ssh[51858]: fatal: /usr/local/etc/autossh/autossh.conf line 18: Bad SSH2 cipher spec 'ciphers_01,ciphers_02,ciphers_03,ciphers_04,ciphers_05,ciphers_06'.

@ndejong

This comment has been minimized.

ndejong commented Sep 11, 2018

These log messages are because you have managed to get yourself into a condition where the ssh_config file has not been rendered, your posting has made me notice an edge case that I have two approaches to resolve - pending

@ndejong

This comment has been minimized.

ndejong commented Sep 11, 2018

Also - another thing here, it's is not clear to me how to "catch" these particular /usr/local/bin/ssh syslog messages to have them appear as Autossh Log messages - nothing I've tried adding in plugins.inc.d/autossh.inc seems to have the effect I'm looking for

@fichtner fichtner self-assigned this Nov 13, 2018

@fichtner

Hi @ndejong,

I apologise for the delay. Here are preliminary comments for eventual inclusion:

  1. The plugin is pretty big which makes initial review difficult. Next step for me would be to use it in action to get a feel for the whole thing.
  2. Kind of split on the OPNsense vs. vendor namespace as initially suggested. Ideally different vendors should be reserved for other projects, commercial and custom plugins. It doesn't matter that much, but it would be nicer to have a single "open source upstream" namespace. What do you think?
  3. rc.d script is quite complex and may be nice to have in FreeBSD per default.

Cheers,
Franco

. /etc/rc.subr
name=autossh
rcvar=${name}_enable

This comment has been minimized.

@fichtner

fichtner Nov 13, 2018

Member

this will eventually clash with freebsd when an rc.d script is added in the package: rename var or maybe add a FreeBSD rc.d script?

@@ -0,0 +1,24 @@
Copyright (c) 2018 Verb Networks Pty Ltd <contact@verbnetworks.com>

This comment has been minimized.

@fichtner

fichtner Nov 13, 2018

Member

This file is implicit from the code lines. and will be in the main LICENSE file merged with all other contributors, but I don't have issues pulling this in. :)

@@ -0,0 +1,30 @@
# Autossh

This comment has been minimized.

@fichtner

fichtner Nov 13, 2018

Member

makes more sense to move this to pkg-descr -- we use the FreeBSD description for general direction, but if you have more to say about your plugin that is the spot since you can read it from the GUI.

<menu>
<VPN>
<Autossh VisibleName="Autossh" cssClass="fa fa-chain fa-fw">
<AutosshTunnels VisibleName="Tunnel Settings" url="/ui/autossh/settings" order="10"/>

This comment has been minimized.

@fichtner

fichtner Nov 13, 2018

Member

mostly opting for easier node names for sorting in larger menus, but so not relevant here. just a comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment