Who can send to a socket bound to INADDR_LOOPBACK? - c++

I'm somewhat new to socket programming, and am confused about the concept of binding a socket to the address INADDR_LOOPBACK, or 127.0.0.1.
If I'm writing server code to listen for messages on a specific port, and I bind a socket to an address as in the following code exerpt...
int sd = socket( PF_INET, SOCK_DGRAM, 0 );
sockaddr_in si;
si.sin_family = AF_INET;
si.sin_addr.s_addr = inet_addr( "127.0.0.1" );
si.sin_port = htons( 9090 );
bind( sd, (sockaddr*)&si, sizeof si )
...my question is: who is able to send to this socket?
I know that other processes running on the same PC as the server process can reach the above socket, by doing a sendto() with a dest_addr argument specifying 127.0.0.1.
But can clients on other PCs on the same network also send to that socket if they know the server's "actual" address? What I mean is: if I run ifconfig on a Linux PC, I'll see an inet address, e.g. 10.138.19.27. Does this mean a client process on a different PC than the server, but on the same network, can send to the server's socket - which was bound to 127.0.0.1 - if the client specifies an address of 10.138.19.27?

Only connections to the loopback adapter (127.0.0.1), and those can only originate from the same machine as the listener since the other interfaces intentionally avoid rounding to that one.
When you don't bind or when you bind to INADDR_ANY (0.0.0.0), you accept connections from all interfaces.
Window 1 Window 2
------------------------------------------ ------------------------------------------
$ nc -l 5678
$ echo test-ip | nc 69.163.162.155 5678 test-ip
$ echo $?
0
$ nc -l 5678
$ echo test-localhost | nc localhost 5678 test-localhost
$ echo $?
0
When you bind to an IP address, you only accept connections directed to that IP address.
Window 1 Window 2
------------------------------------------ ------------------------------------------
$ nc -l 69.163.162.155 5678
$ echo test-localhost | nc localhost 5678
$ echo $?
1
$ echo test-ip | nc 69.163.162.155 5678 test-ip
$ echo $?
0
The same goes for addresses in 127.x.x.x.
Window 1 Window 2
------------------------------------------ ------------------------------------------
$ nc -l localhost 5678
$ echo test-ip | nc 69.163.162.155 5678
$ echo $?
1
$ echo test-localhost | nc localhost 5678 test-localhost
$ echo $?
0
The special thing about 127.x.x.x is that only your own machine can reach 127.x.x.x addresses.

Related

Expect Script to match on multi-line response

I am receiving the response to a Unix cat /etc/hosts and would like to match on this data with Expect - so I can write it local disk.
I have
#!/usr/bin/expect -f
set timeout -1
spawn nc -lvnp 9090
match_max 100000
expect -re {.*(Connection received).*}
puts "Getting hosts file"
send -- "cat /etc/hosts\r"
expect -re "(.*)\n"
The host file is multiple lines and I am unable to construct the correct regular expression to match on it.
Help would be gratefully received
Update
When interact with when the remote service via netcat manually the response interaction looks like this :
nc -lvnp 9090 Listening on 0.0.0.0 9090 Connection received on
192.168.236.135 44686 cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 ubuntu
# The following lines are desirable for IPv6 capable hosts ::1 ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters
my Expect code is :
#!/usr/bin/expect -f
set timeout -1
spawn nc -lvnp 9090
match_max 100000
expect -re {.*(Connection received).*}
puts "******Getting hosts file*******"
log_user 0
send -- "cat /etc/hosts \r"
expect -re "(.*\[\r\n])+"
#expect -re "(.*\[\r|\n]).*"
#expect -re "(.*\[\t|\r|\n]).*"
expect -re "(.*\[\r\n]).*$"
puts "Output 0 string"
puts <<<<$expect_out(0,string)>>>>
puts ""
puts "Output 1 string"
puts <<<<$expect_out(1,string)>>>>
puts ""
puts "Output buffer"
puts <<<<$expect_out(buffer)>>>>
puts ""
puts [open hosts.txt w] $expect_out(buffer)
send -- "\x03"
Just seem to be unable to match on the whole response - I'm not 100% sure if I need to match on EOF or EOL or something else. The newlines and tab are also part of the problem I think.
I basically just to to capture the whole response from the 'send -- "cat /etc/hosts" and write that to disk
turns out he response from the remote server was too quick.
A simple 'sleep 1' was good enough to slow things down
#!/usr/bin/expect -f
set timeout -1
spawn nc -lvnp 9090
match_max 100000
expect -re {.*(Connection received).*}
puts "Getting hosts file"
send -- "cat /etc/hosts\r"
sleep 1
expect -re "(.*)\n"

AWK catching a regular expression

I have been using this little script for months now with success. Today I realize there is one output it cant seem to catch, screen comes up blank with a new prompt:
user#computer ~]$ myscan ipsFile 23
user#computer ~]$
Here is the code
#!/bin/bash
sudo nmap -v -Pn -p T:$2 -reason -i $1 | awk ' {
if (/syn-ack/) {
print "Yes"
c++
}
else if (/no-response|reset|host-unreach/) {
print "No"
c++
}
}
END { print c} '
If I run the nmap against one of the IPs then it returns
Starting Nmap 5.51 ( http://nmap.org ) at 2017-09-26 11:44 CDT
Initiating Parallel DNS resolution of 1 host. at 11:44
Completed Parallel DNS resolution of 1 host. at 11:44, 0.00s elapsed
Initiating Connect Scan at 11:44
Scanning 1.1.1.1 [1 port]
Completed Connect Scan at 11:44, 0.20s elapsed (1 total ports)
Nmap scan report for 1.1.1.1
Host is up, received user-set (0.20s latency).
PORT STATE SERVICE REASON
23/tcp filtered telnet host-unreach
Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.26 seconds
How can I catch the 'host-unreach' portion?
Let's try and debug this. Execute this:
nmap -v -Pn -p T:23 -reason -i ipsFile | awk '{print $0}/syn-ack/{print "Yes";c++}/no-response|reset|host-unreach/{print "No";c++}END {print c}' > out.txt
The only difference here is that the awk script prints $0 (i.e. the output of your nmap calls) to file out.txt. Try to grep your unreach value.
I tried this myself and found that instead of a host-unreach I got a net-unreach. Might be the same thing in your case.
Have you tried piping stderr to stdout like
#!/bin/bash
sudo nmap -v -Pn -p T:$2 -reason -i $1 2>&1 | awk ' {
if (/syn-ack/) {
print "Yes"
c++
}
else if (/no-response|reset|host-unreach/) {
print "No"
c++
}
}
END { print c} '

Does TRAP and Inform Receiver supported in PYSNMP for SNMP v3?

I can see for Trap reciver for SNMP v1 and V2 here:
http://pysnmp.sourceforge.net/examples/v1arch/asyncore/manager/ntfrcv/transport-tweaks.html
It does not support SNMP v3 trap.
Is there something for v3 trap receiver in PYSNMP?
And also is there something for inform receiver ?
Yes, here is a SNMPv3 notification receiver example. The same code works for INFORMs as well. In fact, the same code supports SNMPv1 and v2c TRAPs/INFORMs.
UPDATED:
SNMPv1/v2c TRAP receiver is obliged to check SNMP community name in the incoming message (a very light security measure). That's why you need to configure SNMP community name to SNMP engine on the receiving end.
If you need more details on SNMP engine operations (like peer's network address), there is a collection of callbacks placed at strategic locations inside pysnmp which you can listen to to gather the information about currently running request. Here's an example. The getTransportInfo call can also be used, but it's considered obsolete by now.
You can experiment with it by sending INFORMs to demo.snmplabs.com (port 162).
Thanks, #llya Etingof 's solution in GitHub.
example:
"""
Multiple SNMP USM users
+++++++++++++++++++++++
Receive SNMP TRAP/INFORM messages with the following options:
* SNMPv1/SNMPv2c
* with SNMP community "public"
* over IPv4/UDP, listening at 127.0.0.1:162
* SNMPv3
* with USM users:
* 'usr-md5-des', auth: MD5, priv DES, ContextEngineId: 8000000001020304
* 'usr-md5-none', auth: MD5, priv NONE, ContextEngineId: 8000000001020304
* 'usr-sha-aes128', auth: SHA, priv AES, ContextEngineId: 8000000001020304
* over IPv4/UDP, listening at 127.0.0.1:162
* print received data on stdout
Either of the following Net-SNMP commands will send notifications to this
receiver:
| $ snmptrap -v2c -c public 127.0.0.1:162 123 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 s test
| $ snmptrap -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 -e 8000000001020304 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1
| $ snmptrap -v3 -u usr-md5-none -l authNoPriv -A authkey1 -e 8000000001020304 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1
| $ snmpinform -v3 -u usr-sha-aes128 -l authPriv -a SHA -A authkey1 -x AES -X privkey1 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1
"""#
from pysnmp.entity import engine, config
from pysnmp.carrier.asyncore.dgram import udp
from pysnmp.entity.rfc3413 import ntfrcv
from pysnmp.proto.api import v2c
# Create SNMP engine with autogenernated engineID and pre-bound
# to socket transport dispatcher
snmpEngine = engine.SnmpEngine()
# Transport setup
# UDP over IPv4
config.addTransport(
snmpEngine,
udp.domainName,
udp.UdpTransport().openServerMode(('127.0.0.1', 162))
)
# SNMPv1/2c setup
config.addV1System(snmpEngine, 'my-area', 'public')
# SNMPv3/USM setup
# user: usr-md5-des, auth: MD5, priv DES
config.addV3User(
snmpEngine, 'usr-md5-des',
config.usmHMACMD5AuthProtocol, 'authkey1',
config.usmDESPrivProtocol, 'privkey1'
)
# user: usr-md5-des, auth: MD5, priv DES, securityEngineId: 8000000001020304
# this USM entry is used for TRAP receiving purposes
config.addV3User(
snmpEngine, 'usr-md5-des',
config.usmHMACMD5AuthProtocol, 'authkey1',
config.usmDESPrivProtocol, 'privkey1',
securityEngineId=v2c.OctetString(hexValue='8000000001020304')
)
# user: usr-md5-none, auth: MD5, priv NONE
config.addV3User(
snmpEngine, 'usr-md5-none',
config.usmHMACMD5AuthProtocol, 'authkey1'
)
# user: usr-md5-none, auth: MD5, priv NONE, securityEngineId: 8000000001020304
# this USM entry is used for TRAP receiving purposes
config.addV3User(
snmpEngine, 'usr-md5-none',
config.usmHMACMD5AuthProtocol, 'authkey1',
securityEngineId=v2c.OctetString(hexValue='8000000001020304')
)
# user: usr-sha-aes128, auth: SHA, priv AES
config.addV3User(
snmpEngine, 'usr-sha-aes128',
config.usmHMACSHAAuthProtocol, 'authkey1',
config.usmAesCfb128Protocol, 'privkey1'
)
# user: usr-sha-aes128, auth: SHA, priv AES, securityEngineId: 8000000001020304
# this USM entry is used for TRAP receiving purposes
config.addV3User(
snmpEngine, 'usr-sha-aes128',
config.usmHMACSHAAuthProtocol, 'authkey1',
config.usmAesCfb128Protocol, 'privkey1',
securityEngineId=v2c.OctetString(hexValue='8000000001020304')
)
# Callback function for receiving notifications
# noinspection PyUnusedLocal,PyUnusedLocal,PyUnusedLocal
def cbFun(snmpEngine, stateReference, contextEngineId, contextName,
varBinds, cbCtx):
print('Notification from ContextEngineId "%s", ContextName "%s"' % (
contextEngineId.prettyPrint(), contextName.prettyPrint()))
for name, val in varBinds:
print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
# Register SNMP Application at the SNMP engine
ntfrcv.NotificationReceiver(snmpEngine, cbFun)
snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish
# Run I/O dispatcher which would receive queries and send confirmations
try:
snmpEngine.transportDispatcher.runDispatcher()
except:
snmpEngine.transportDispatcher.closeDispatcher()
raise
command:
| $ snmptrap -v2c -c public 127.0.0.1:162 123 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 s test
| $ snmptrap -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 -e 8000000001020304 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1
| $ snmptrap -v3 -u usr-md5-none -l authNoPriv -A authkey1 -e 8000000001020304 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1
| $ snmpinform -v3 -u usr-sha-aes128 -l authPriv -a SHA -A authkey1 -x AES -X privkey1 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1
stdout:
Notification from ContextEngineId "0x80004fb80543794f53335afe60", ContextName ""
1.3.6.1.2.1.1.3.0 = 123
1.3.6.1.6.3.1.1.4.1.0 = 1.3.6.1.6.3.1.1.5.1
1.3.6.1.2.1.1.5.0 = test
Notification from ContextEngineId "0x80001f88809f7b5c26ef1e1c5e00000000", ContextName ""
1.3.6.1.2.1.1.3.0 = 123
1.3.6.1.6.3.1.1.4.1.0 = 1.3.6.1.6.3.1.1.5.1
Notification from ContextEngineId "0x80001f88809f7b5c26ef1e1c5e00000000", ContextName ""
1.3.6.1.2.1.1.3.0 = 123
1.3.6.1.6.3.1.1.4.1.0 = 1.3.6.1.6.3.1.1.5.1
Notification from ContextEngineId "0x80001f88809f7b5c26ef1e1c5e00000000", ContextName ""
1.3.6.1.2.1.1.3.0 = 123
1.3.6.1.6.3.1.1.4.1.0 = 1.3.6.1.6.3.1.1.5.1
I get the following error when executing:
'#python3 EXAMPLE-above.py'
'#udp.domainName,
AttributeError: module 'pysnmp.carrier.asyncore.dgram.udp' has no attribute 'domainName' '
Centos 7
Python 3.6.8
pysnmp 5.0.0
pysmi-0.3.4
pyasn1-0.4.8
net-snmp5.8.1-pre
'#python3 -v -c 'import pysnmp' 2>&1 | grep pysmi --> produce nothing'
'#python -v -c 'import pysnmp' 2>&1 | grep pysmi'
'#zipimport: found 100 names in /usr/lib/python2.7/site-packages/pysmi-0.3.4-py2.7.egg'
'#python3 -v -c 'import pysnmp' 2>&1 | grep pyasn1'
'# zipimport: found 77 names in '/usr/local/lib/python3.6/site-packages/pyasn1-0.4.8-py3.6.egg'
FIXED: git clone all the dependancie source, unzip the packages, cd package-source-dir then: #python3 setup.py install
As this is my first python/snmp project there is most probably better/cleanr ways to resolve.
Would appreciate to know the correct way.
Happy hacking :)

Different processes showed as same PID within netstat

I spawn few processes using the Python multiprocessing module.
However when I call netstat -nptl, each ip:port listeners listed under the same PID.
I'm using Python 2.7 on Ubuntu 14.04.
netstat -V
>> net-tools 1.60
>> netstat 1.42 (2001-04-15)
Relevant code:
import unittest
import multiprocessing
import socket
import os
import time
import ex1
class Listener(multiprocessing.Process):
def __init__(self, _ttl):
super(Listener, self).__init__()
self.ttl = _ttl
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind(('localhost', 0))
def get_pid(self):
return self.pid
def get_name(self):
return self.socket.getsockname()
def run(self):
self.socket.listen(1)
time.sleep(self.ttl)
def listen(self):
self.start()
class TestEx1(unittest.TestCase):
def test_is_legal_ip(self):
# Legal IP
assert(ex1.is_legal_ip("1.1.1.1:55555"))
assert(ex1.is_legal_ip("0.1.1.255:55555"))
assert(ex1.is_legal_ip("0.0.0.0:55555"))
assert(ex1.is_legal_ip("255.255.255.255:55555"))
assert(ex1.is_legal_ip("0.1.2.3:55555"))
# Illegal IP
assert(not ex1.is_legal_ip("256.1.1.1:55555"))
assert(not ex1.is_legal_ip("1.256.1:55555"))
assert(not ex1.is_legal_ip("1.1.1.1.1:55555"))
assert(not ex1.is_legal_ip("1.a.1.1:55555"))
assert(not ex1.is_legal_ip("1.1001.1.1:55555"))
def test_address_to_pid(self):
# Create 3 listener processes
listener1 = Listener(22)
listener2 = Listener(22)
listener3 = Listener(22)
# Start listening
listener1.listen()
listener2.listen()
listener3.listen()
print listener1.get_pid()
print listener2.get_pid()
print listener3.get_pid()
# For each listener, get appropriate ip:port
address1 = str(str(listener1.get_name()[0])) + \
":" + str(listener1.get_name()[1])
address2 = str(str(listener2.get_name()[0])) + \
":" + str(listener2.get_name()[1])
address3 = str(str(listener3.get_name()[0])) + \
":" + str(listener3.get_name()[1])
# Check if address_to_pid() works as expected.
#assert(str(ex1.address_to_pid(address1)) == str(listener1.get_pid()))
#assert(str(ex1.address_to_pid(address2)) == str(listener2.get_pid()))
#assert(str(ex1.address_to_pid(address3)) == str(listener3.get_pid()))
# Waits for the listener processes to finish
listener2.join()
listener2.join()
listener3.join()
if __name__ == "__main__":
unittest.main()
Output:
4193
4194
4195
..
----------------------------------------------------------------------
Ran 2 tests in 22.019s
OK
Netstat -nptl output:
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.1.1:53 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:37529 0.0.0.0:* LISTEN 4192/python
tcp 0 0 127.0.0.1:53402 0.0.0.0:* LISTEN 4192/python
tcp 0 0 127.0.0.1:49214 0.0.0.0:* LISTEN 4192/python
tcp 1 0 192.168.46.136:49475 209.20.75.76:80 CLOSE_WAIT 2968/plugin_host
tcp 70 0 192.168.46.136:60432 91.189.92.7:443 CLOSE_WAIT 3553/unity-scope-ho
tcp6 0 0 ::1:631 :::* LISTEN -
Using my Mac OS 10.9.5 (Python 2.7.3), I could reproduce the same behavior. After several try-and-error, it turned out that it's because the socket objects are shared among the processes. (lsof -p <pid> helps to identify listening sockets.)
When I made following change to Listener class, each process started to listen on its own port number by its own PID.
def get_name(self):
# this method cannot refer to socket object any more
# self.sockname should be initialized as "not-listening" at __init__
return self.sockname
def run(self):
# Instantiate socket at run
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind(('localhost', 0))
self.sockname = self.socket.getsockname()
# Listener knows sockname
print self.sockname
self.socket.listen(1)
time.sleep(self.ttl)
This behavior should be the same as Ubuntu's Python and netstat.
self.sockname remains "not-listening" at original process
To listen on port as independent process, sockets need to be created at run method of a Listener object (New process calls this method after creating copy of the object). However variables updated in this copied object in the new process are not reflected to the original objects in original process.

Extract client IP address from tcpdump (on OpenBSD)

I am trying to extract and collect some client IP addresses using the command tcpdump, but just can't figure out how to get grep/sed/awk to give me just the first IP address of the output. If I run the following
# tcpdump -t -i vlan4 -n ip dst host 192.168.2
tcpdump: listening on vlan4, link-type EN10MB
tcpdump: WARNING: compensating for unaligned libpcap packets
10.28.6.1.29447 > 192.168.2.62.22: P 3758838950:3758839034..
10.28.6.1.29447 > 192.168.2.62.22: P 84:136(52) ack 117..
10.28.6.1.29447 > 192.168.2.62.22: P 136:188(52) ack 233..
10.28.6.1.29447 > 192.168.2.62.22: . ack 349 win 251 (DF)..
I just want to get the first ip on each line without the port number. So from the above output I want to get just.....
10.28.6.1
10.28.6.1
10.28.6.1
10.28.6.1
Thanks
try this cut line:
cut -f1-4 -d "."
test with your data:
kent$ echo "10.28.6.1.29447 > 192.168.2.62.22: P 3758838950:3758839034..
10.28.6.1.29447 > 192.168.2.62.22: P 84:136(52) ack 117..
10.28.6.1.29447 > 192.168.2.62.22: P 136:188(52) ack 233..
10.28.6.1.29447 > 192.168.2.62.22: . ack 349 win 251 (DF).."|cut -f1-4 -d "."
10.28.6.1
10.28.6.1
10.28.6.1
10.28.6.1
perl -lane '$F[0]=~s/(.*)\..*/$1/g;print $F[0]' your_file