Configuration
The VisionAppster Engine consists of a bunch of software modules that are available to all apps. The va-engine
service that runs on the background is actually a VisionAppster app itself. It is started through va-run
as any app could.
The app is called init.qml
and stored in the init
directory under the VisionAppster installation root. There is also an alternative app called api-init.qml
that is intended for running a fixed set of apps and to publish their APIs. To configure the va-engine
service, the easiest way is to modify the init.qml
script.
The location of the VisionAppster installation and thus the init.qml
script varies depending on platform.
- Windows:
C:\Program Files\VisionAppster\init
- Generic Linux:
/opt/visionappster/init
- Flatpak: Typing
flatpak info -l com.visionappster.Builder
will give you the root of the installed Flatpak. The init app can be found infiles/opt/visionappster/init
under the Flatpak root.
Since the Engine lets one to install and run new components through the HTTP interface, it is extremely important to set up access control correctly. A failure in doing so will easily lead into a remote code execution vulnerability.
Network interface
The default behavior of the init.qml
app is to bind the web server to the loopback interface only. This blocks out all external connection attempts. api-init.qml
binds to all available interfaces by default.
The web server can be bound to a specific interface or to all available interfaces. For example:
127.0.0.1:2015
- Bind to IPv4 loopback only.[::1]:2015
- Bind to IPv6 loopback only.0.0.0.0:2015
- Bind to all IPv4 interfaces.[::]:2015
- Bind to all IPv6 interfaces.192.168.1.5:2015
- Bind to a specific IPv4 address.
The port number (2015) could be anything else, but some client software may assume the standard port.
// Listen port 2015 on all IPv4 interfaces
webServer.start("0.0.0.0:2015");
IP-based access control
The web server supports IP subnet based access control. If no access control rules have been specified, requests from any IP will be accepted. Once a single rule has been set up, the default behavior changes to deny requests. The access control rules work on the TCP layer, blocking the connection before HTTP has a chance to parse the request.
The access control mechanism maintains a list of rules that either allow or deny access based on the client's IP address. The first matching rule will determine the fate of the client. The following example denies access from a certain evil IP subnet.
// Block evil IPs.
webServer.denyFrom('64.233.160.0/19');
// An empty address means "everybody". Allow everybody else.
webServer.allowFrom('');
The allowFrom
and denyFrom
functions accept IPv4 and IPv6 addresses and subnets. Examples:
webServer.allowFrom('10.0.0.0/255.255.255.0'); // IPv4 address/netmask
webServer.denyFrom('10.0.0.0/24'); // Same in CIDR notation
webServer.allowFrom('10.0.0.1'); // IPv4 host address
webServer.denyFrom('fe80::a65d:36ff:fec8:aced'); // IPv6 host address
webServer.allowFrom('fe80::/64'); // IPv6 subnet
webServer.denyFrom(''); // Any IP address (v4 or v6)
CORS
CORS is a technique implemented by browsers to allow web pages to make requests to servers they did not originate from. Since this is generally unsafe, the target server must be explicitly configured to accept the requests.
The Engine's web server disallows CORS requests by default. That is, scripts loaded from a web server other than the Engine's own will not be able to make requests to it. Note however that this only applies to browsers. A malicious Node.js script run locally can still make requests to the server. The api-init.qml
app does not expose unsafe features to the web server and therefore enables CORS:
WebServer
{
id: webServer
corsEnabled: true
}
This allows CORS requests made by any script independent of its origin. For a more fine-grained control one can specify which domains are allowed to make CORS requests:
WebServer
{
id: webServer
corsEnabled: true
corsOrigins: ['https://doc.visionappster.com', 'http://safe.site:8888']
}