<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ted X Toth</title>
	<atom:link href="http://nall.com/tedx/feed/" rel="self" type="application/rss+xml" />
	<link>http://nall.com/tedx</link>
	<description></description>
	<lastBuildDate>Mon, 27 Sep 2010 21:23:25 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Node Servers at SELinux MLS Level</title>
		<link>http://nall.com/tedx/2010/07/node-servers-at-selinux-mls-level/</link>
		<comments>http://nall.com/tedx/2010/07/node-servers-at-selinux-mls-level/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 20:35:51 +0000</pubDate>
		<dc:creator>tedx</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://nall.com/tedx/?p=56</guid>
		<description><![CDATA[Current xinetd functionality allows you to start a server at the level of a connection but it is limited to only servicing that connection. Apache 1.3 (configured with &#8216;ServerType inetd&#8217;) can be run by xinetd this way quite effectively however it is exec&#8217;d for each connection. For this experiment I&#8217;m using RHEL6 with selinux-policy-mls installed [...]]]></description>
			<content:encoded><![CDATA[<p>Current xinetd functionality allows you to start a server at the level of a connection but it is limited to only servicing that connection. Apache 1.3 (configured with &#8216;ServerType inetd&#8217;) can be run by xinetd this way quite effectively however it is exec&#8217;d for each connection.  For this experiment  I&#8217;m using RHEL6 with selinux-policy-mls installed and to keep it simple I&#8217;m running SELinux in permissive mode. Configuration of labeled networking was accomplished as follows:</p>
<pre>
1. Create a CIPSO DOI so that the system can understand packets (both inbound
and outbound) that have a CIPSO DOI of "2".

 # netlabelctl cipsov4 add local doi:2

2. In this example we are going to use address selectors to ensure we only
send CIPSO "local" traffic to localhost so we need to delete the existing
legacy domain selector and re-create it with the address selectors:

 # netlabelctl map del default
 # netlabelctl map add default address:0.0.0.0/0 protocol:unlbl

3. We need to tell the system that for all the packets destined for localhost
we want to assign CIPSO tags/labels using DOI "2":

 # netlabelctl map add default address:127.0.0.1 protocol:cipsov4,2
</pre>
<p> <a href="http://github.com/pgriess/node-webworker">node-webworker</a> by Peter Griess is utilized to implement a super servers that runs servers at level that can process multiple connection and my <a href="http://github.com/tedx/node-selinux">node-selinux</a> module for doing SELinux stuff.</p>
<p>The master:</p>
<pre>
var path = require('path');
var Worker = require('webworker/webworker').Worker;
var sys = require('sys');
var net = require('net');
var selinux = require('selinux_node');

var workers = new Array();

var s = new selinux.SELinux();

var srv = net.createServer(function (stream) {
    stream.pause();
    sys.puts("connection " + stream.fd);

    s.getpeercon(stream.fd, function (con) {
        var w;
    	if (typeof(workers[con]) == 'undefined') {
	   sys.puts("create new worker for context " + con);
	   s.setexeccon(con);
	   w = new Worker(path.join(__dirname, 'xworker.js'));
	   workers[con] = w;
    	}
	else {
	     w = workers[con];
	     sys.puts("use existing worker ", w);
    	}

    	w.postMessage({ 'banner' : 'Hello, world!' }, stream.fd);
    }
);
}).listen(5000, "127.0.0.1");
</pre>
<p>The worker:</p>
<pre>
var assert = require('assert');
var http = require('http');
var sys = require('sys');
var net = require('net');

var banner = undefined;

var srv = http.createServer(function(req, resp) {
    resp.writeHead(200, {'Content-Type' : 'text/plain'});
    resp.write(banner + ' (pid ' + process.pid + ')\n');
    resp.end();
});

onmessage = function(msg) {
    assert.ok(msg.fd &#038;&#038; msg.fd > 0);

    sys.print('Got message!\n');

    banner = msg.data.banner;

    var s = new net.Stream(msg.fd);
    s.type = srv.type;
    s.server = srv;
    s.resume();
    srv.emit('connection', s);
};
</pre>
<p>Test can be done simply by using curl  and newrole for example:</p>
<pre>
curl http://127.0.0.1:5000
</pre>
<p>To test at different levels run:</p>
<pre>
newrole -l s0-s0 -- -c "curl http://127.0.0.1:5000"
</pre>
<p>Server test output:</p>
<pre>
[tedx@localhost ~]$ node fdmaster.js
connection 6
create new worker for context staff_u:staff_r:staff_t:SystemLow-SystemHigh
Got message!
connection 9
create new worker for context staff_u:staff_r:staff_t:SystemLow
Got message!
connection 12
create new worker for context staff_u:staff_r:staff_t:UNCLASSIFIED
Got message!
connection 15
use existing worker
[object Object]
Got message!
</pre>
<p>Test run output:</p>
<pre>
[tedx@localhost ~]$ curl http://127.0.0.1:5000
Hello, world! (pid 23425)
[tedx@localhost ~]$ newrole -l s0-s0 -- -c "curl http://127.0.0.1:5000"
Password:
Hello, world! (pid 23476)
[tedx@localhost ~]$ newrole -l s1-s1 -- -c "curl http://127.0.0.1:5000"
Password:
Hello, world! (pid 23530)
[tedx@localhost ~]$ newrole -l s1-s1 -- -c "curl http://127.0.0.1:5000"
Password:
Hello, world! (pid 23530)
</pre>
<p>Notice that the last two requests went to the same child.</p>
<p>What&#8217;s missing you ask, policy! The dirty little secret of SELinux is policy which I&#8217;ve totally ignored in this example. If you were to create a unique SELinux type for your worker you&#8217;d probably do this by creating a script that wraps node and assign it a file context and you&#8217;d write policy to transition from the file context to your workers unique context. Luckily the webworker constructor can handle this by allowing you to specify the node command to use when running the worker script.</p>
<pre>
w = new Worker(path.join(__dirname, 'xworker.js'), {'path' : '/usr/local/bin/node-my-unique-selinux-type'});
</pre>
]]></content:encoded>
			<wfw:commentRss>http://nall.com/tedx/2010/07/node-servers-at-selinux-mls-level/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Node.js server and xinetd</title>
		<link>http://nall.com/tedx/2010/06/node-js-server-and-xinetd/</link>
		<comments>http://nall.com/tedx/2010/06/node-js-server-and-xinetd/#comments</comments>
		<pubDate>Tue, 01 Jun 2010 13:10:27 +0000</pubDate>
		<dc:creator>tedx</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://nall.com/tedx/?p=4</guid>
		<description><![CDATA[I&#8217;ve been playing with Node.js and decided to see if I could create a service that could be run out of xinetd. Running a service out of xinetd requires that it use stdin (fd 0) for it&#8217;s connection. To accomplish this I subclassed from http.Server adding a connectFD method to be able to set the [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been playing with <a href="http://nodejs.org/">Node.js</a>  and decided to see if I could create a service that could be run out of xinetd. Running a service out of xinetd requires that it use stdin (fd 0) for it&#8217;s connection. To accomplish this I subclassed from http.Server adding a connectFD method to be able to set the file descriptor for the server to use.</p>
<pre>var sys = require('sys'),
net = require('net'),
http = require('http');

var Server = function (listener) {
    http.Server.call(this, listener);
};

sys.inherits(Server, http.Server);

exports.Server = Server;

Server.prototype.connectFD = function (fd) {
    var s = new net.Stream(fd);
    s.type = this.type;
    s.server = this;
    s.resume();
    this.emit('connection', s);
}
</pre>
<p>I named this xhttp.js.</p>
<p>You need a service configuration file in /etc/xinetd.d to specify the port and command similar to:</p>
<pre>
# default: on
# description: node.js based service
#
service xnode
{
        disable                 = no
        port                    = 49000
        socket_type             = stream
        protocol                = tcp
        wait                    = no
        user                    = root
        server                  = &lt;path of node executable&gt;
        server_args             = &lt;path of services js file&gt;
        env             = NODE_PATH=&lt;path to xhttp.js file&gt;
}
</pre>
<p>Don&#8217;t forget to set the required path names.</p>
<p>For my service I decided to have a little fun and have it run commands on the server and return the output.</p>
<pre>
var sys = require('sys'),
    xhttp = require('xhttp'),
    url = require('url'),
    exec  = require('child_process').exec;

var requestHandler = function (req, res) {
    var cmd = url.parse(req.url).pathname;
    cmd = cmd.substring(1);
    qstr = url.parse(req.url, true).query
    for (key in qstr) {
        cmd  = cmd + " " + qstr[key];
    }

    var child = exec(cmd,
        function (error, stdout, stderr) {
            res.writeHead(200, {'Content-Type': 'text/plain'});
            if (error !== null) {
                res.write(stderr);
            }
            else {
                res.write(stdout);
            }
            res.end();
        });
}
var s = new xhttp.Server(requestHandler);
s.connectFD(0);
</pre>
<p>After adding the xinetd configuration file to /etc/xinetd.d restart xinetd and try something like :</p>
<p><a href="http://localhost:49000/ls?arg0=-la&#038;arg1=/tmp">http://localhost:49000/ls?arg0=-la&#038;arg1=/tmp</a></p>
]]></content:encoded>
			<wfw:commentRss>http://nall.com/tedx/2010/06/node-js-server-and-xinetd/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

