PDA

View Full Version : Command to open a tcp port on linux/solaris?


Felecha
08-05-2008, 05:33 PM
I write automated test software, and I want some way to issue a command line in linux and in solaris that will open a tcp port on the system. Then the application I am testing is told to use that port and it should generate an error - "Port not available".

I found a utility in Linux - netcat. If I say

netcat -l -p 11111

it will open port 11111 until I end the command with ctrl-C. That actually would work for Linux but I need the tests to run on solaris as well and I havent found anything yet for solaris.

netcat is not a system command, it's a separate utility someone wrote that is bundled into RH Linux, as far as I can tell

Thanks

Nothinman
08-05-2008, 06:19 PM
I'm not that familiar with Solaris but I doubt you'll find anything other than netcat for it, you'll just need to find a package or compile it yourself. Of course you could just pick a random daemon on your system and set it up to listen on that port too.

QuixoticOne
08-05-2008, 07:17 PM
netcat / netpipes and similar are good approaches.
You can get a lot of already compiled installable packages of open source tools for SOLARIS from sites like this:
http://www.sunfreeware.com/
http://www.blastwave.org/

If you use BASH shell scripting you may be able to do things like this:
echo foo > /dev/tcp/192.168.101.101/1111
echo foo > /dev/udp/192.168.101.101/1111
where the 192.168.101.101 would be your remote host name / IP to contact and 1111 the example port number.

netcat / netpipes / et. al. are more flexible than this approach.

There may be other tools that are more commonly used in solaris though I don't recall what they'd be at the moment.

ScottMac
08-05-2008, 08:40 PM
I believe you'd put an entry in /etc/services.

Here's the top few lines from RHEL 5.1:
# service-name port/protocol [aliases ...] [# comment]

tcpmux 1/tcp # TCP port service multiplexer
tcpmux 1/udp # TCP port service multiplexer
rje 5/tcp # Remote Job Entry
rje 5/udp # Remote Job Entry
echo 7/tcp
echo 7/udp
discard 9/tcp sink null
discard 9/udp sink null
systat 11/tcp users
systat 11/udp users
daytime 13/tcp
daytime 13/udp
qotd 17/tcp quote
qotd 17/udp quote
msp 18/tcp # message send protocol
msp 18/udp # message send protocol
chargen 19/tcp ttytst source
chargen 19/udp ttytst source

This is the file that assigns ports and port types to a process, IIRC.

Good Luck

Scott

edit: space compression rears its ugly head ... just do a "more /etc/services" and you'll get the idea

Felecha
08-06-2008, 08:46 AM
Rats! Such good ideas, and I learned some stuff but for the particular testing need, I dont see how I can make it work. Maybe I don't seee YET?

In a little more detail, I am using SilkTest to drive the testing of a database management app. The database servers are out there on Linux and Solaris, the app being tested is on Windows. We have some homegrown java utilities that can talk across the network to an agent process on the servers that are built for RPC, so from the SilkTest scripts on windows I can call one of our java functions from the library:

ExecCommand(system,command)

That goes to the agent on <system> which then runs the command as if it were running there from a shell script. So I could say

ExecCommand("blackhorse","nc -l -p 11111") and port 11111 would open on blackhorse. (nc is netcat)

The thing is that the tests I am creating are not just for my use here, they are intended to be used by anyone in the company, and there is a certain amount of setup required if someone is going to run the tests. It would not be a good solution to require that they have to install opensource packages on their test systems, or add to the services and reboot as part of the testing. Netcat seems to come with RH that we have here, but even that is not perhaps a reliable thing for other testers. So my hope was for a system command that, if I could run it in a shell, I could then build it into the SilkTest scripts with our ExecCommand function.

Still, thanks for the tips, I didnt know about /etc/services.

And the thing of echo foo, here's what I got sending it from palehorse to blackhorse

[flokey@palehorse:~]echo foo > /dev/tcp/10.24.112.55/11111
bash: connect: Connection refused
bash: /dev/tcp/10.24.112.55/11111: Connection refused
[flokey@palehorse:~]

Nothinman
08-06-2008, 08:49 AM
I believe you'd put an entry in /etc/services.

All that does is affect the name to port number mappings for things like getservbyname(3).

Felecha
08-06-2008, 11:54 AM
echo foo > /dev/tcp/192.168.101.101/1111

I found a lot of webpages related to /dev/tcp, but I finally concluded that they are talking about connecting to an existing socket at 1111, not creating one where there is none. Is that right?

Cause one of the things I wanted to devise a test for was that the app under test will open a dialog for you to configure something, and you are to enter a name for it and declare a port to be used. It is specified that the dialog will present a default of port 5001. If 5001 is in use, it would offer 5002. The user will probably enter his own choice, but the functional spec says that is the behavior - start at 5001 and if it's in use, keep looking until a port is found that is not in use, and THAT is what will show in the dialog text field. So the idea was that before calling up the dialog, I would open port 5001 and expect the dialog to then open showing 5002. It also is supposed to check that the port a user enters on his own is valid. For that one I just write it so that SilkTest enters 2049 (the nfsd port) and clicks OK on the dialog, and presto! - the error comes up saying 2049 is not a valid port to use. But for the testing of the default I wanted to "manually" grab 5001

yinan
08-06-2008, 01:30 PM
Even if the port or whatever is opened the firewall an application has to be running on that port.

QuixoticOne
08-07-2008, 06:32 AM
netcat
netpipes
bash's /dev/tcp/... (see man bash for details)
socat
inetd
xinetd
daemontools
ssh
stunnel
daemontools/ucspi-tcp
openvpn
and a normal IPSEC VPN
are the major ways excepting things like SOAP servers, Web Services, RPC, CORBA, ODBC, JINI / Java RMI, and such to facilitate communication between peer hosts, or a client and a server.

The /etc/services bit above isn't quite correct, services just gives a service "name" to port number translation table that itself doesn't
do anything else, but you can define arbitrary server processes to run when comminications are established over UDP or TCP links to
a given server machine; you set that up with inetd / xinetd / /etc/services or DJB's daemontools/ucspi-tcp. This is an easy and standard
sort of way to make a server "always listen" on predefined TCP or UDB ports and for that server to hand off the incoming traffic / connections
to defined server applications when traffic does appear.

Usually you'd use netcat / netpipes to establish a pipeline type link to over the network and use the output of the pipe or standard IO channel
the pipe / nc is connected to to input/output to a server process or a file on the server or whatever. Your example doesn't really speak
to how you're plumbing your pipes to server processes or files or whatever. Your examples show the nc *being* the invoked server
process, but by itself it is kind of useless if you don't specify a useful location or additional program on the server that the nc/pipe will
send its output to or take its input from.
These are the typical sorts of configurations, and you'd use command line arguments or a shell script wrapper to set up
any I/O redirections or command line arguments for nc / netpipes / whatever to get the whole thing working.
Client Transmits OUTPUT ---> network ----> Server file being made from data coming over the network
Client Transmits OUTPUT ---> network ---> Server process that reads the data as input
Client Reads INPUT <---- network <---- Server file being sent over the network
Client Reads INPUT <--- network <--- Server process sending its output data over the network to a remote client

If you just want a static set of ports waiting for client connections on the server, check out inetd/xinetd and /etc/services etc.

If you just want a simple pipe type of facility over the network, netpipes, netcat.

If you want some data security and some kind of standardized way to redirect server ports over the network, check out ssh and sshd
and stunnel, they are there to 'securely' transport data from server files or processes to clients. Both the client and server need to have
compatible ssh or stunnel software running, however the ssh facility can take arbitrary server processes or ports and redirect their
outputs and inputs over the network, for instance it is typical to run X windows over SSH, or use SSH to start up a remote bash shell
and have the shell's input / output directed over the network along obviously with any commands the shell runs itself. You can
set up predefined key based authentication between the server and client processes and have particular server processes run
when a given client connects.

If you're doing JAVA ESQUE code on both ends it wouldn't be uncommon to use things like RMI / JINI / CORBA / JDBC / DCE / RPC / J2EE / SOAP/ WSDL type of APIs in the JAVA programs on the client and the server to wrap up the communications layer and make things
work, though the programs would have to be designed to do this sort of thing and sometimes it is more complex than is needed if all
you wanted is socket level TCP/UDP communications.

Of course if you were writing JAVA applications and all you wanted was socket level communications, there are network IO classes that
give you that straight in JAVA without needing any additional utilities like netpipes/netcat, but the programs would have had to have been
written to support such networking of course.

Turn off the firewall blocking of any needed ports of course if there is any.

You could also do things like statically or dynamically set up VPN or PPP links from one machine to the other and in that case all the
ports on one machine's VPN interface could be open to the other machine's VPN interface bypassing things like NAT or firewalls on
the physical network between the machines.

I think if you write yourself a simple script on the server
#!/bin/bash
echo "Hello world"

and then cause it to be invoked by netcat (or set it up as an inetd/xinetd TCP service on a given port) and send its output over the
network that may be a simpler starting point than trying to set up test programs to work if you don't quite understand how to plumb them
into the picture.

QuixoticOne
08-07-2008, 07:44 AM
And here's how you can plumb in a simple shell
script to act as a service called localtest to be launched by inetd on port localtest (1111 in /etc/services) for handling incoming TCP connection requests.
This example is from a recent build of Solaris Express / Open Nevada, though it would be sort of similar for older / different Solaris versions.

On LINUX it'd be a simpler case of just editing /etc/services, and /etc/inetd.conf (or /etc/xinetd.d/localtest or whatever it exactly would be with xinetd) and doing a kill -HUP on the inetd process to get it to restart with the new configuration.
(of course that's assuming inetd is installed and enabled in init.d / system services).

In either case the principle and function is the same though the configuration administration commands on the server side are a little different between Solaris / LINUX.


bash-3.2# tail -1 /etc/services
localtest 1111/tcp # local test program



bash-3.2# cat /opt/test/localtest.sh
#!/bin/bash
echo "This is a test."
date



bash-3.2# cat /opt/test/svc_network_test.xml
<?xml version='1.0'?>
<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<service_bundle type='manifest' name='export'>
<service name='network/localtest' type='service' version='0'>
<restarter>
<service_fmri value='svc:/network/inetd:default'/>
</restarter>
<property_group name='inetd' type='framework'>
<stability value='Evolving'/>
<propval name='isrpc' type='boolean' value='false'/>
<propval name='name' type='astring' value='localtest'/>
</property_group>
<instance name='stream' enabled='true'>
<exec_method name='inetd_start' type='method' exec='/opt/test/localtest.sh' timeout_seconds='0'>
<method_context>
<method_credential user='root' group='root'/>
</method_context>
</exec_method>
<exec_method name='inetd_disable' type='method' exec=':kill' timeout_seconds='0'>
<method_context/>
</exec_method>
<property_group name='inetd' type='framework'>
<propval name='endpoint_type' type='astring' value='stream'/>
<propval name='proto' type='astring' value='tcp6'/>
<propval name='wait' type='boolean' value='false'/>
</property_group>
</instance>
<stability value='Unstable'/>
<template>
<common_name>
<loctext xml:lang='C'>echo</loctext>
</common_name>
</template>
</service>
</service_bundle>



bash-3.2# svccfg import svc_network_localtest.xml && echo DONE



bash-3.2# inetadm -l network/localtest
SCOPE NAME=VALUE
name="localtest"
endpoint_type="stream"
proto="tcp6"
isrpc=FALSE
wait=FALSE
exec="/opt/test/localtest.sh"
user="root"
default bind_addr=""
default bind_fail_max=-1
default bind_fail_interval=-1
default max_con_rate=-1
default max_copies=-1
default con_rate_offline=-1
default failrate_cnt=40
default failrate_interval=60
default inherit_env=TRUE
default tcp_trace=FALSE
default tcp_wrappers=FALSE
default connection_backlog=10



bash-3.2# netstat -na | grep 1111
*.1111 *.* 0 0 49152 0 LISTEN
*.1111 *.* 0 0 49152 0 LISTEN



bash-3.2# svcs | grep -i localtest
online 4:19:54 svc:/network/localtest:stream



bash-3.2# nc 127.0.0.1 1111
This is a test.
Thu Aug 7 04:33:36 PDT 2008

bash-3.2# nc 127.0.0.1 1111
This is a test.
Thu Aug 7 04:33:38 PDT 2008


On SXCE/ON as it turns out (nc) was installed by default right from the distribution media given the installation options I chose, so perhaps you're running a much older Solaris or your sysadmin just didn't install it yet.

In this example nc isn't really needed to do anything unless one were to use it at the client side since the server side's networking is handled completely by inetd and the custom server process that takes input from stdin and sends output to stdout. Any client program / process that TCP connected to the server port would get that data back from the server, nc is just one example of a way to do it on the client side in this case.

And here's a different example of what a client side bash script might do using the same inetd server/service as an example:

bash-3.2# cat < /dev/tcp/127.0.0.1/1111
This is a test.
Thu Aug 7 04:43:29 PDT 2008


In this case the server and client are on the same machine so I just use 127.0.0.1 the localhost address as the server's address, of course it'd work the same on other IP addresses on the server too.