UDP hole punching is working with google colab but not other local nats - c

I'm making an p2p application with c. I made basic program which communicates peer by udp hole punching. Now my program works fine when I run a program from my PC an another from google colab.
But when tried it with my friend's pc which under another ISP (different ISP from mine) it doesn't work. Again if my friend tries it with google colab it works fine.
I tried stun test in my pc, colab, and my friends results are like these:
Mine:
test I = 1
test II = 0
test III = 0
test I(2) = 1
is nat = 1
mapped IP same = 1
hairpin = 0
preserver port = 1
Primary: Independent Mapping, Port Dependent Filter, preserves ports, no hairpin
Return value is 0x000017
colab:
test I = 1
test II = 0
test III = 0
test I(2) = 1
is nat = 1
mapped IP same = 1
hairpin = 1
preserver port = 1
Primary: Independent Mapping, Port Dependent Filter, preserves ports, will hairpin
Return value is 0x000007
my friend's:
test I = 1
test II = 0
test III = 0
test I(2) = 1
is nat = 1
mapped IP same = 1
hairpin = 0
preserver port = 1
Primary: Independent Mapping, Port Dependent Filter, preserves ports, no hairpin
Return value is 0x000017
I used ttl 255 where pinging with my fiends nat shows required ttl of 62. Is it the cause?Ping command shows ttl 112 for google colab. I'm currently trying this program from Bangladesh.

Related

Vagrant Vmware static IP

I'm using Windows10 + Vagrant and Vmware Workstation 16.2.2 as a Vagrant provider.
I want to run virtual Debian 10 with a static IP 192.168.232.160 and I want to use NAT mode only. Here is my config:
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "generic/debian10"
config.vm.box_check_update = true
config.vm.network "public_network", ip: "192.168.232.160" # with this string VM crushes every time
config.vm.provider "vmware_desktop" do |v|
v.vmx['displayname'] = "VDebian10"
v.gui = true
v.vmx["memsize"] = "2048"
v.vmx["numvcpus"] = "2"
v.vmx["ethernet0.connectiontype"] = "nat"
v.vmx["ethernet0.present"] = "TRUE"
v.vmx["ethernet0.addresstype"] = "generated"
v.vmx["ethernet1.present"] = "FALSE"
end
end
if I try to run above mentioned config then VM "VDebian10" runs and crushes every time with the error "batch_action.rb:86:in `block (2 levels) in run".
But if I comment the string "config.vm.network "public_network", ip: "192.168.232.160" then the VM runs successfully with a newly assigned DHCP IP address from 192.168.232.xx range.
In addition, I found some parameters in .vmx file regarding to this block:
v.vmx["ethernet0.connectiontype"] = "nat"
v.vmx["ethernet0.present"] = "TRUE"
v.vmx["ethernet0.addresstype"] = "generated"
v.vmx["ethernet1.present"] = "FALSE"
If I don't use that block then this VM runs with two adapters - NAT and bridged. But I need to run NAT adapter only.
How can I assign a static IP in this config?
I tried to use the parameter "config.vm.network "public_network", ip: " 192.168.232.160" but it doesn't work.

How do i record JANUS signal as wav file?

I am testing an interoperability between modems. one of my modem did support JANUS and I believe UnetStack base Subnero Modem Phy[3] also support JANUS. How can i send and record JANUS signal which i can use for preliminary testing for other modem ? Can someone please provide basic snippet ?
UnetStack indeed has an implementation of JANUS that is, by default, configured on phy[3].
You can check this on your modem (the sample outputs here are from unet audio SDOAM, and so your modem parameters might vary somewhat):
> phy[3]
« PHY »
[org.arl.unet.phy.PhysicalChannelParam]
fec = 7
fecList ⤇ [LDPC1, LDPC2, LDPC3, LDPC4, LDPC5, LDPC6, ICONV2]
frameDuration ⤇ 1.1
frameLength = 8
janus = true
[org.arl.yoda.FhbfskParam]
chiplen = 1
fmin = 9520.0
fstep = 160.0
hops = 13
scrambler = 0
sync = true
tukey = true
[org.arl.yoda.ModemChannelParam]
modulation = fhbfsk
preamble = (2400 samples)
threshold = 0.0
(I have dropped a few parameters that are not relevant to the discussion here to keep the output concise)
The key parameters to take note of:
modulation = fhbfsk and janus = true setup the modulation for JANUS
fmin = 9520.0, fstep = 160.0 and hops = 13 are the modulation parameters to setup fhbfsk as required by JANUS
fec = 7 chooses ICONV2 from the fecList, as required by JANUS
threshold = 0.0 indicates that reception of JANUS frames is disabled
NOTE: If your modem is a Subnero M25 series, the standard JANUS band is out of the modem's ~20-30 kHz operating band. In that case, the JANUS scheme is auto-configured to a higher frequency (which you will see as fmin in your modem). Do note that this frequency is important to match for interop with any other modem that might support JANUS at a higher frequency band.
To enable JANUS reception, you need to:
phy[3].threshold = 0.3
To avoid any other detections from CONTROL and DATA packets, we might want to disable those:
phy[1].threshold = 0
phy[2].threshold = 0
At this point, you could make a transmission by typing phy << new TxJanusFrameReq() and put a hydrophone next to the modem to record the transmitted signal as a wav file.
However, I'm assuming you would prefer to record on the modem itself, rather than with an external hydrophone. To do that, you can enable the loopback mode on the modem, and set up the modem to record the received signal:
phy.loopback = true # enable loopback
phy.fullduplex = true # enable full duplex so we can record while transmitting
phy[3].basebandRx = true # enable capture of received baseband signal
subscribe phy # show notifications from phy on shell
Now if you do a transmission, you should see a RxBasebandSignalNtf with the captured signal:
> phy << new TxJanusFrameReq()
AGREE
phy >> RxFrameStartNtf:INFORM[type:#3 rxTime:492455709 rxDuration:1100000 detector:0.96]
phy >> TxFrameNtf:INFORM[type:#3 txTime:492456016]
phy >> RxJanusFrameNtf:INFORM[type:#3 classUserID:0 appType:0 appData:0 mobility:false canForward:true txRxFlag:true rxTime:492455708 rssi:-44.2 cfo:0.0]
phy >> RxBasebandSignalNtf:INFORM[adc:1 rxTime:492455708 rssi:-44.2 preamble:3 fc:12000.0 fs:12000.0 (13200 baseband samples)]
That notification has your signal in baseband complex format. You can save it to a file:
save 'x.txt', ntf.signal, 2
To convert to a wav file, you'll need to load this signal and convert to passband. Here's some example Python code to do this:
import numpy as np
import scipy.io.wavfile as wav
import arlpy.signal as asig
x = np.genfromtxt('x.txt', delimiter=',')
x = x[:,0] + 1j * x[:,1]
x = asig.bb2pb(x, 12000, 12000, 96000)
wav.write('x.wav', 96000, x)
NOTE: You will need to replace the fd and fc of 12000 respectively, by whatever is the fs and fc fields in your modem's RxBasebandSignalNtf. For Unet audio, it is 12000 for both, but for Subnero M25 series modems it is probably 24000.
Now you have your wav file at 96 kSa/s!
You could also plot a spectrogram to check if you wanted to:
import arlpy.plot as plt
plt.specgram(x, fs=96000)
I have an issue while recording the signal. Modem refuse to send the JANUS frame. It looks like something is not correctly set on my end, specially fmin = 12000.0 , fstep = 160.0 and hops = 13. The Actual modem won't let me set the fmin to 9520.0 and automatically configured on lowest fmin = 12000. How can i calculate corresponding parameters for fmin=12000.
Although your suggestion do work on the unet audio.
Here is my modem logs:
> phy[3]
« PHY »
[org.arl.unet.DatagramParam]
MTU ⤇ 0
RTU ⤇ 0
[org.arl.unet.phy.PhysicalChannelParam]
dataRate ⤇ 64.0
errorDetection ⤇ true
fec = 7
fecList ⤇ [LDPC1, LDPC2, LDPC3, LDPC4, LDPC5, LDPC6, ICONV2]
frameDuration ⤇ 1.0
frameLength = 8
janus = true
llr = false
maxFrameLength ⤇ 56
powerLevel = -10.0
[org.arl.yoda.FhbfskParam]
chiplen = 1
fmin = 12000.0
fstep = 160.0
hops = 13
scrambler = 0
sync = true
tukey = true
[org.arl.yoda.ModemChannelParam]
basebandExtra = 0
basebandRx = true
modulation = fhbfsk
preamble = (2400 samples)
test = false
threshold = 0.3
valid ⤇ false
> phy << new TxJanusFrameReq()
REFUSE: Frame type not setup correctly
phy >> FAILURE: Timed out

Winsock Bluetooth get socket handle of active connection

So I am trying to monitor the traffic of an active Bluetooth connection on my PC. I am able to get get several information about the active connection to the remote device, e.g. SOCKADDR_BTH. I thought I could use the port information of the remote device and bind a socket to it in order to monitor the traffic, but the device discovery is not providing the port information, see below:
Device name:WH-1000XM2
Device connected: 65536
Device remembered: 1
Device authenticated: 1
Remote Bluetooth device is 0x702605aba41d, server channel = 0
Local Bluetooth device is 0x84ef18b8460a, server channel = 0
Here is the corresponding code spinet:
/*Preparing the queryset return buffer*/
pwsaResults = (LPWSAQUERYSET)buffer;
pwsaResults->dwNameSpace = NS_BTH;
pwsaResults->dwSize = sizeof(WSAQUERYSET);
BTH_QUERY_DEVICE qDev{};
qDev.length = 1;
BLOB blb;
blb.cbSize = sizeof(BTH_QUERY_DEVICE);
blb.pBlobData = reinterpret_cast<PBYTE>(&qDev);
pwsaResults->lpBlob = &blb;
while (WSALookupServiceNext(hLookup, LUP_RETURN_ADDR | LUP_RETURN_NAME | LUP_CONTAINERS | LUP_RETURN_TYPE | LUP_RES_SERVICE | LUP_FLUSHCACH, &swSize, pwsaResults) == NO_ERROR)
{
pAddrInfo = (CSADDR_INFO*)pwsaResults->lpcsaBuffer;
pBtSockRemote = (SOCKADDR_BTH*)(pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr);
pBtSockLocal = (SOCKADDR_BTH*)(pwsaResults->lpcsaBuffer->LocalAddr.lpSockaddr);
wprintf(L"Device #:%d\n", nDevicesFound);
wprintf(L"Device name:%s\n", pwsaResults->lpszServiceInstanceName);
wprintf(L"Device connected: %d\n", (pwsaResults->dwOutputFlags & BTHNS_RESULT_DEVICE_CONNECTED));
wprintf(L"Device remembered: %d\n", (pwsaResults->dwOutputFlags & BTHNS_RESULT_DEVICE_REMEMBERED)>0);
wprintf(L"Device authenticated: %d\n", (pwsaResults->dwOutputFlags & BTHNS_RESULT_DEVICE_AUTHENTICATED)>0);
wprintf(L"Remote Bluetooth device is 0x%04x%08x, server channel = %d\n",
GET_NAP(pBtSockRemote->btAddr), GET_SAP(pBtSockRemote->btAddr), pBtSockRemote->port);
wprintf(L"Local Bluetooth device is 0x%04x%08x, server channel = %d\n",
GET_NAP(pBtSockLocal->btAddr), GET_SAP(pBtSockLocal->btAddr), pBtSockLocal->port);
nDevicesFound++;
}
I was thinking about using WSAIoctl in order to sniff the traffic.

Python3 TypeError: sequence item 0: expected a bytes-like object, int found

I'm trying to send an array over TCP from a server-like script to a client-like one. The array is variable, so the data is sent using packets and then joined together at the client.
The data I'm trying to send is from the MNIST hand-written digits dataset for Deep Learning. The server-side code is:
tcp = '127.0.0.1'
port = 1234
buffer_size = 4096
(X_train, y_train), (X_test, y_test) = mnist.load_data()
test_data = (X_test, y_test)
# Client-side Deep Learning stuff
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((tcp, port))
x = pickle.dumps(test_data)
s.sendall(x)
s.close()
The client-side script loads a Neural Network that uses the test data to predict classes. The script for listening to said data is:
tcp = '127.0.0.1'
port = 1234
buffer_size = 4096
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((tcp, port))
print ('Listening...')
s.listen(1)
conn, addr = s.accept()
data_arr = []
while True:
data_pack = conn.recv(buffer_size)
if not data: break
data_pack += data
my_pickle = b"".join(data_pack)
test_data = pickle.loads(my_pickle)
print ("Received: " + test_data)
conn.close()
# Irrelevant Deep Learning stuff...
The server sends the data without a hitch, but the client crashes when trying to join the packets received by the client (my_pickle = ...) with the following error:
TypeError: sequence item 0: expected a bytes-like object, int found
How should I format the join in order to recreate the data sent and use it for the rest of the script?
I ended up using both Pickle and ZeroMQ to handle the comunication protocol. An advantage of this method is that I can send more than one data package.
On the client side:
ip = '127.0.0.1'
port = '1234'
# ZeroMQ context
context = zmq.Context()
# Setting up protocol (client)
sock = context.socket(zmq.REQ)
sock.bind('tcp://'+ip+':'+port)
print('Waiting for connection at tcp://'+ip+':'+port+'...')
sock.send(pickle.dumps(X_send))
X_answer = sock.recv()
sock.send(pickle.dumps(y_send))
print('Data sent. Waiting for classification...')
y_answer = sock.recv()
print('Done.')
And on the server side:
# ZeroMQ Context
context = zmq.Context()
# Setting up protocol (server)
sock = context.socket(zmq.REP)
ip = '127.0.0.1'
port = '1234'
sock.connect('tcp://'+ip+':'+port)
print('Listening to tcp://'+ip+':'+port+'...')
X_message = sock.recv()
X_test = pickle.loads(X_message)
sock.send(pickle.dumps(X_message))
y_message = sock.recv()
y_test = pickle.loads(y_message)
print('Data received. Starting classification...')
# Classification process
sock.send(pickle.dumps(y_message))
print('Done.')

Setting ICMP match with POX controller

I'm trying to add a flow entry to a switch using POX controller, my code is:
fm = of.ofp_flow_mod()
fm.match.in_port = 1
fm.priority = 33001
fm.match.dl_type = 0x800
fm.match.nw_src = IPAddr("10.0.0.1")
fm.match.nw_dst = IPAddr("10.0.0.5")
fm.actions.append(of.ofp_action_output( port = 2 ) )
event.connection.send( fm )
However, when I ping from 10.0.0.1 to 10.0.0.5 there's no reply.
What can be the problem ?
(I've also added symmetric flow for the ICMP reply)
Thank you
(Note: I changed 10.0.0.5 to 10.0.0.3 in the following examples, as I tested with a 1 switch, 3 hosts topology in mininet.)
Your problem is that ARP requests are not getting through. You'll need to add two additional rules to let messages of dl_type=0x0806 through. So:
def _handle_ConnectionUp (event):
fm = of.ofp_flow_mod()
fm.match.in_port = 1
fm.priority = 33001
fm.match.dl_type = 0x0800
fm.match.nw_src = IPAddr("10.0.0.1")
fm.match.nw_dst = IPAddr("10.0.0.3")
fm.actions.append(of.ofp_action_output( port = 3 ) )
event.connection.send( fm )
fm = of.ofp_flow_mod()
fm.match.in_port = 3
fm.priority = 33001
fm.match.dl_type = 0x0800
fm.match.nw_src = IPAddr("10.0.0.3")
fm.match.nw_dst = IPAddr("10.0.0.1")
fm.actions.append(of.ofp_action_output( port = 1 ) )
event.connection.send( fm )
fm = of.ofp_flow_mod()
fm.match.in_port = 1
fm.priority = 33001
fm.match.dl_type = 0x0806
fm.actions.append(of.ofp_action_output( port = 3 ) )
event.connection.send( fm )
fm = of.ofp_flow_mod()
fm.match.in_port = 3
fm.priority = 33001
fm.match.dl_type = 0x0806
fm.actions.append(of.ofp_action_output( port = 1 ) )
event.connection.send( fm )
If you don't have any loops in your network, you can also just add a single rule that floods the packets on every port except the one it came from.
fm = of.ofp_flow_mod()
fm.priority = 33001
fm.match.dl_type = 0x0806
fm.actions.append(of.ofp_action_output( port = of.OFPP_FLOOD ) )
event.connection.send( fm )
Some more information: When you send an ICMP echo request destined towards an IP address, the following happens:
The hosts sends out an ARP request ("who has IP 10.0.0.3?") to find out the hardware MAC address for the next hop.
The host then sends out the ICMP packet towards the next hop.
If the initial query yields no response, the ICMP packet is not sent as the host does not know where to send it next. You can see this in the tcpdump example at the end of this answer.
This is the output from mininet:
mininet#mininet-vm:~$ sudo mn --topo single,3 --mac --switch ovsk,protocols=OpenFlow10 --controller remote
*** Creating network
*** Adding controller
*** Adding hosts:
h1 h2 h3
*** Adding switches:
s1
*** Adding links:
(h1, s1) (h2, s1) (h3, s1)
*** Configuring hosts
h1 h2 h3
*** Starting controller
c0
*** Starting 1 switches
s1 ...
*** Starting CLI:
mininet> pingall
*** Ping: testing ping reachability
h1 -> X h3
h2 -> X X
h3 -> h1 X
*** Results: 66% dropped (2/6 received)
mininet>
So what if we already "know" what the next hop is? In this case we can tell ping to send the ICMP IPv4 packet out a specific interface. It will not use ARP then. However, the receiver of the ping request will still try to use ARP to figure out how to send the response. The request will arrive, but the response will not.
You can force the initial ping to be sent to a specific interface, without using an ARP request by running:
# Run this on host h1
h1 ping -I h1-eth0 -c1 10.0.0.3
Then the initial ICMP packet will also go through even if you do not have ARP rules setup (as the nw_src and nw_dst match). If you run tcpdump on h3 (Run xterm h3 and in the new terminal tcpdump), you can see that the ICMP message arrives in this case, but the return message does not.
# Run this on host h3
root#mininet-vm:~# tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on h3-eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
20:20:19.428465 IP 10.0.0.1 > 10.0.0.3: ICMP echo request, id 24690, seq 1, length 64
20:20:19.428481 ARP, Request who-has 10.0.0.1 tell 10.0.0.3, length 28
20:20:20.428094 ARP, Request who-has 10.0.0.1 tell 10.0.0.3, length 28
20:20:21.428097 ARP, Request who-has 10.0.0.1 tell 10.0.0.3, length 28
The long sequence of ARP requests at the end is the receiving host trying to figure out over which interface it should send the response back.

Resources