Error when trying to connect/send Access request to Freeradius server - freeradius

I'm using freeradius on docker and is trying to get a response back when access request is sent.
When radtest is run using: radtest bob testpw 127.0.0.1 1812 sharedSecret
Sent Access-Request Id 18 from 0.0.0.0:56219 to 127.0.0.1:1812 length 73
User-Name = "bob"
User-Password = "testpw"
NAS-IP-Address = 172.17.0.2
NAS-Port = 1812
Message-Authenticator = 0x00
Cleartext-Password = "testpw"
Sent Access-Request Id 18 from 0.0.0.0:56219 to 127.0.0.1:1812 length 73
User-Name = "bob"
User-Password = "testpw"
NAS-IP-Address = 172.17.0.2
NAS-Port = 1812
Message-Authenticator = 0x00
Cleartext-Password = "testpw"
Sent Access-Request Id 18 from 0.0.0.0:56219 to 127.0.0.1:1812 length 73
User-Name = "bob"
User-Password = "testpw"
NAS-IP-Address = 172.17.0.2
NAS-Port = 1812
Message-Authenticator = 0x00
Cleartext-Password = "testpw"
(0) No reply from server for ID 18 socket 3
I know that this normally happens when the shared secret is wrong, but it is the same as mentioned in the configuration files.
When debugged I get the bellow error.
Ignoring request to auth address * port 1812 bound to server default
from unknown client 172.17.0.3 port 60699 proto udp Ready to process
requests
error is given without any response back from the server.
The clients.conf file is as follows;
client dockernet {
ipaddr = 172.17.0.0/16
secret = sharedSecret
}
and authorise file;
bob Cleartext-Password := "testpw"
default file;
server default {
listen {
type = auth
ipv4addr = *
# ipv6addr = *
# ipaddr = *
port = 5
# interface = eth0
# clients = per_socket_clients
recv_buff = 65536
limit {
max_connections = 16
lifetime = 0
idle_timeout = 30
}
}
authorize {
update request {
&Tmp-String-0 := "%{string:User-Password}"
&User-Password := "%{string:Tmp-String-0}"
}
# filter_username
# filter_password
preprocess
# operator-name
# cui
# auth_log
chap
mschap
digest
# wimax
# IPASS
suffix
# ntdomain
eap {
ok = return
# updated = return
}
#
# unix
# Read the 'users' file. In v3, this is located in
# raddb/mods-config/files/authorize
files
-sql
# smbpasswd
-ldap
# daily
expiration
logintime
pap
# Autz-Type Status-Server {
# }
}
authenticate {
ntlm_auth
Auth-Type PAP {
pap
}
Auth-Type CHAP {
chap
}
Auth-Type MS-CHAP {
mschap
}
mschap
digest
# pam
# Auth-Type LDAP {
# ldap
# }
#
# Allow EAP authentication.
eap
# Auth-Type eap {
# eap {
# handled = 1
# }
# if (handled && (Response-Packet-Type == Access-Challenge)) {
# attr_filter.access_challenge.post-auth
# handled # override the "updated" code from attr_filter
# }
# }
}
#
# Pre-accounting. Decide which accounting type to use.
#
preacct {
preprocess
#
# Merge Acct-[Input|Output]-Gigawords and Acct-[Input-Output]-Octets
# into a single 64bit counter Acct-[Input|Output]-Octets64.
#
# acct_counters64
# update request {
# &FreeRADIUS-Acct-Session-Start-Time = "%{expr: %l - %{%{Acct-Session-Time}:-0} - %{%{Acct-Delay-Time}:-0}}"
# }
acct_unique
# IPASS
suffix
# ntdomain
#
# Read the 'acct_users' file
files
}
An Access-Accept or an Access-Reject is expected. But no response, when debugged and gives the above error in the logs.

It works! after I changed the clients.conf file to have a netmask and not ipaddr = 172.17.0.0/16
client dockernet {
ipaddr = 172.17.0.0
secret = sharedSecret
netmask = 24
shortname = dockernet
}
This article helped me https://linux.die.net/man/5/clients.conf

Related

Telegraf http listener v2: unable to send JSON with string values

I'm trying to send this very simple JSON string to Telegraf to be saved into InfluxDB:
{ "id": "id_123", "value": 10 }
So the request would be this: curl -i -XPOST 'http://localhost:8080/telegraf' --data-binary '{"id": "id_123","value": 10}'
When I make that request, I get the following answer: HTTP/1.1 204 No Content Date: Tue, 20 Apr 2021 13:02:49 GMT but when I check what was written to database, there is only value field:
select * from http_listener_v2
time host influxdb_database value
---- ---- ----------------- -----
1618923747863479914 my.host.com my_db 10
What am I doing wrong?
Here's my Telegraf config:
[global_tags]
[agent]
interval = "10s"
round_interval = true
metric_batch_size = 1000
metric_buffer_limit = 10000
collection_jitter = "0s"
flush_interval = "10s"
flush_jitter = "0s"
precision = ""
hostname = ""
omit_hostname = false
# OUTPUTS
[[outputs.influxdb]]
urls = ["http://127.0.0.1:8086"]
database = "telegraf"
username = "xxx"
password = "xxx"
[outputs.influxdb.tagdrop]
influxdb_database = ["*"]
[[outputs.influxdb]]
urls = ["http://127.0.0.1:8086"]
database = "httplistener"
username = "xxx"
password = "xxx"
[outputs.influxdb.tagpass]
influxdb_database = ["httplistener"]
# INPUTS
## system
[[inputs.cpu]]
percpu = true
totalcpu = true
collect_cpu_time = false
report_active = false
[[inputs.disk]]
ignore_fs = ["tmpfs", "devtmpfs", "devfs", "iso9660", "overlay", "aufs", "squashfs"]
[[inputs.mem]]
[[inputs.swap]]
[[inputs.system]]
## http listener
[[inputs.http_listener_v2]]
service_address = ":8080"
path = "/telegraf"
methods = ["POST", "PUT"]
data_source = "body"
data_format = "json"
[inputs.http_listener_v2.tags]
influxdb_database = "httplistener"
Use json_string_fields = ["id"]

Unable to get response http Post to local express app from Kapacitor stream

I am following SE Thread to get some response to HTTP POST on an express node. But unable to get any response from kapacitor.
Environment
I am using Windows 10 via PowerShell.
I am connected to an InfluxDB internal Server which is mentioned in the kapacitor.conf and have a TICKscript to stream data via it.
kapacitor.conf
hostname = "134.102.97.81"
data_dir = "C:\\Users\\des\\.kapacitor"
skip-config-overrides = true
default-retention-policy = ""
[alert]
persist-topics = true
[http]
bind-address = ":9092"
auth-enabled = false
log-enabled = true
write-tracing = false
pprof-enabled = false
https-enabled = false
https-certificate = "/etc/ssl/kapacitor.pem"
https-private-key = ""
shutdown-timeout = "10s"
shared-secret = ""
[replay]
dir = "C:\\Users\\des\\.kapacitor\\replay"
[storage]
boltdb = "C:\\Users\\des\\.kapacitor\\kapacitor.db"
[task]
dir = "C:\\Users\\des\\.kapacitor\\tasks"
snapshot-interval = "1m0s"
[load]
enabled = false
dir = "C:\\Users\\des\\.kapacitor\\load"
[[influxdb]]
enabled = true
name = "DB5Server"
default = true
urls = ["https://influxdb.internal.server.address:8086"]
username = "user"
password = "password"
ssl-ca = ""
ssl-cert = ""
ssl-key = ""
insecure-skip-verify = true
timeout = "0s"
disable-subscriptions = true
subscription-protocol = "https"
subscription-mode = "cluster"
kapacitor-hostname = ""
http-port = 0
udp-bind = ""
udp-buffer = 1000
udp-read-buffer = 0
startup-timeout = "5m0s"
subscriptions-sync-interval = "1m0s"
[influxdb.excluded-subscriptions]
_kapacitor = ["autogen"]
[logging]
file = "STDERR"
level = "DEBUG"
[config-override]
enabled = true
[[httppost]]
endpoint = "kapacitor"
url = "http://localhost:1440"
headers = { Content-Type = "application/json;charset=UTF-8"}
alert-template = "{\"id\": {{.ID}}}"
The daemon runs without any problems.
test2.tick
dbrp "DBTEST"."autogen"
stream
|from()
.measurement('humid')
|alert()
.info(lambda: TRUE)
.post()
.endpoint('kapacitor')
Already defined the task .\kapacitor.exe define bc_1 -tick test2.tick
Enabled it .\kapacitor.exe enable bc_1
The status shows nothing:
.\kapacitor.exe show bc_1
ID: bc_1
Error:
Template:
Type: stream
Status: enabled
Executing: true
Created: 13 Mar 19 15:33 CET
Modified: 13 Mar 19 16:23 CET
LastEnabled: 13 Mar 19 16:23 CET
Databases Retention Policies: ["NIMBLE"."autogen"]
TICKscript:
dbrp "TESTDB"."autogen"
stream
|from()
.measurement('humid')
|alert()
.info(lambda: TRUE)
.post()
.endpoint('kapacitor')
DOT:
digraph bc_1 {
graph [throughput="0.00 points/s"];
stream0 [avg_exec_time_ns="0s" errors="0" working_cardinality="0" ];
stream0 -> from1 [processed="0"];
from1 [avg_exec_time_ns="0s" errors="0" working_cardinality="0" ];
from1 -> alert2 [processed="0"];
alert2 [alerts_inhibited="0" alerts_triggered="0" avg_exec_time_ns="0s" crits_triggered="0" errors="0" infos_triggered="0" oks_triggered="0" warns_triggered="0" working_cardinality="0" ];
}
The Daemon logs provide this for the task
ts=2019-03-13T16:25:23.640+01:00 lvl=debug msg="starting enabled task on startup" service=task_store task=bc_1
ts=2019-03-13T16:25:23.677+01:00 lvl=debug msg="starting task" service=kapacitor task_master=main task=bc_1
ts=2019-03-13T16:25:23.678+01:00 lvl=info msg="started task" service=kapacitor task_master=main task=bc_1
ts=2019-03-13T16:25:23.679+01:00 lvl=debug msg="listing dot" service=kapacitor task_master=main dot="digraph bc_1 {\nstream0 -> from1;\nfrom1 -> alert2;\n}"
ts=2019-03-13T16:25:23.679+01:00 lvl=debug msg="started task during startup" service=task_store task=bc_1
ts=2019-03-13T16:25:23.680+01:00 lvl=debug msg="opened service" source=srv service=*task_store.Service
ts=2019-03-13T16:25:23.680+01:00 lvl=debug msg="opening service" source=srv service=*replay.Service
ts=2019-03-13T16:25:23.681+01:00 lvl=debug msg="skipping recording, metadata is already correct" service=replay recording_id=353d8417-285d-4fd9-b32f-15a82600f804
ts=2019-03-13T16:25:23.682+01:00 lvl=debug msg="skipping recording, metadata is already correct" service=replay recording_id=a8bb5c69-9f20-4f4d-8f84-109170b6f583
But I get nothing on the Express Node side. The code is exactly the same as that in the above mentioned SE thread.
Any Help as to how to capture stream from Kapacitor on HTTP Post? I already have a live system that is pushing information into the dedicated database already
I was able to shift focus from stream to batch in the above query. I have documented the complete process on medium.com.
Some Files:
kapacitor.gen.conf
hostname = "my-windows-10"
data_dir = "C:\\Users\\<user>\\.kapacitor"
skip-config-overrides = true
default-retention-policy = ""
[alert]
persist-topics = true
[http]
bind-address = ":9092"
auth-enabled = false
log-enabled = true
write-tracing = false
pprof-enabled = false
https-enabled = false
https-certificate = "/etc/ssl/kapacitor.pem"
https-private-key = ""
shutdown-timeout = "10s"
shared-secret = ""
[replay]
dir = "C:\\Users\\des\\.kapacitor\\replay"
[storage]
boltdb = "C:\\Users\\des\\.kapacitor\\kapacitor.db"
[task]
dir = "C:\\Users\\des\\.kapacitor\\tasks"
snapshot-interval = "1m0s"
[load]
enabled = false
dir = "C:\\Users\\des\\.kapacitor\\load"
[[influxdb]]
enabled = true
name = "default"
default = true
urls = ["http://127.0.0.1:8086"]
username = ""
password = ""
ssl-ca = ""
ssl-cert = ""
ssl-key = ""
insecure-skip-verify = true
timeout = "0s"
disable-subscriptions = true
subscription-protocol = "http"
subscription-mode = "cluster"
kapacitor-hostname = ""
http-port = 0
udp-bind = ""
udp-buffer = 1000
udp-read-buffer = 0
startup-timeout = "5m0s"
subscriptions-sync-interval = "1m0s"
[influxdb.excluded-subscriptions]
_kapacitor = ["autogen"]
[logging]
file = "STDERR"
level = "DEBUG"
[config-override]
enabled = true
# Subsequent Section describes what this conf does
[[httppost]]
endpoint = "kap"
url = "http://127.0.0.1:30001/kapacitor"
headers = { "Content-Type" = "application/json"}
TICKScript
var data = batch
| query('SELECT "v" FROM "telegraf_test"."autogen"."humid"')
.period(5s)
.every(10s)
data
|httpPost()
.endpoint('kap')
Define the Task
.\kapacitor.exe define batch_test -tick .\batch_test.tick -dbrp DBTEST.autogen
I suspect the hostname was michieveous where it was set to localhost previously but I set it my machine's hostname and instead used the IP address 127.0.0.1 whereever localhost was mentioned

ESP 8266 MicroPython getting partial data for POST

I'm trying to set up a simple HTTP web server on ESP8266-01 (1MB flash), which has latest 1.9.3 MicroPython firmware. The purpose is to be able to configure the credentials for the home network, to which the STA interface would ultimately connect.
So the code at high level does this:
Turns on the AP interface
Some one would connect to 192.168.0.1/index.html, which would have a form for username and password. We just need to put admin/admin. Clicking on Submit button should do a POST to 192.168.0.1/configure.html
Configure.html is a web page with a form, where SSID and password would be input. I hope you can follow more details by looking at the code below
I am facing two problems:
The total number of bytes that I receive when index.html form is submitted are not complete. I get to around Referrer (that too partial), all a total of around 560 bytes. This is when I do it from mobile browser. Funny thing, it always gets exactly those many bytes. I can share what I get if that's going to help.
The watch dog timer sometimes reboots my module. I'm doing most of the suggested changes in my code - using small sleeps. Is there any way in MicroPython on ESP8266, through which I can 'feed' the WDT so that it does not 'time-out' and reboot my module?
The following is my code:
import gc
import network
gc.collect()
import machine
gc.collect()
import ubinascii
gc.collect()
import ujson
gc.collect()
import uos
gc.collect()
import utime
gc.collect()
import socket
gc.collect()
import select
gc.collect()
html = """<!DOCTYPE html>
<html>
<head> <title>Ouroboros IoT Login</title> </head>
<body>
<form action="configure.html" method="POST">
Username : <input type="text" name="username"></br>
Password: <input type="password" name="password" ></br>
<input type="submit" value="submit" name="submit">
</form>
</body>
</html>
"""
login_fail_html = """<!DOCTYPE html>
<html>
<head> <title>Ouroboros IoT Login</title> </head>
<body>
<h2>Incorrect Credentials!</h2><br>Please login<br>
<form action="configure.html" method="POST">
Username : <input type="text" name="username"></br>
Password: <input type="password" name="password" ></br>
<input type="submit" value="submit" name="submit">
</form>
</body>
</html>
"""
# Check if file exists
def fileExists(fileName):
try:
uos.stat(fileName)
print("File " + fileName + " found!")
return True
except OSError:
print("No file " + fileName + " found!")
return False
# Turns WiFi ON for configuration
def turn_wifi_on():
# Setup the AP interface
ap_if = network.WLAN(network.AP_IF)
ap_if.active(False)
ap_if.active(True)
# Get the MACADDRESS - without any spaces
macaddress = ubinascii.hexlify(ap_if.config('mac'),'').decode()
ap_if.config(essid="OUB1_"+macaddress, password="12345678")
#ap_if.config(essid="OUB1_"+macaddress)
ap_if.ifconfig(('192.168.0.1', '255.255.255.0', '192.168.0.1', '192.168.0.1'))
# Configure the AP to static IPs
def turn_wifi_off():
ap_if = network.WLAN(network.AP_IF)
ap_if.active(False)
# Find out the stored IoT secret content
def get_iot_secret():
fileName = 'alpha.txt'
if fileExists(fileName):
f = open(fileName)
content_str = f.read()
f.close()
return content_str
else:
return 'asdasrefwefefergf9rerf3n4r23irn1n32f'
# Find out the stored home network credential if exist
def get_wifi_config():
fileName = 'wifi.conf'
if fileExists(fileName):
f = open(fileName)
content_str = f.read()
f.close()
content = ujson.loads(content_str)
return content
else:
return None
# Set the home network credentials
def save_wifi_config(essid, passphrase):
f = open('wifi.conf', 'w')
config = {'essid':essid, 'passphrase':passphrase}
config_str = ujson.dumps(config)
f.write(config_str)
f.close()
# Find out the stored login credentials
def get_login_config():
fileName = 'login.conf'
if fileExists(fileName):
f = open(fileName)
content_str = f.read()
f.close()
content = ujson.loads(content_str)
return content
else:
# No file exists so far, so use the admin/admin credentials
return {'user':'admin','password':'admin'}
# Set the login credentials
def save_login_config(user, password):
f = open('login.conf', 'w')
config = {'user':user, 'password':password}
config_str = ujson.dumps(config)
f.write(config_str)
f.close()
def turn_gpio_on(device_num):
# Device Num to Pin Mapping
if device_num == 0:
pin_num = 0
elif device_num == 1:
pin_num = 2
# Check Pin
pin = machine.Pin(pin_num)
if pin.value() == 0:
pin.on()
# else it is already at HIGH state, nothing to do
def turn_gpio_off(device_num):
# Device Num to Pin Mapping
if device_num == 0:
pin_num = 0
elif device_num == 1:
pin_num = 2
# Check Pin
pin = machine.Pin(pin_num)
if pin.value() == 1:
pin.off()
# else it is already at LOW state, nothing to do
def init_pin(device_num):
# Device Num to Pin Mapping
if device_num == 0:
pin_num = 0
elif device_num == 1:
pin_num = 2
#open GPIO0 in output mode & turn it off by default
pin = machine.Pin(pin_num, machine.Pin.OUT)
# Turn off both GPIO initially
turn_gpio_off(device_num)
# Find out the post parameters in a dictionary
def get_post_params(req):
print("Inside GET POST PARAMS : req = " + req)
post_params = req.split('\r\n')[-1:][0]
# Check if the post body contains the necessary fields
# Split the post_params by &
# params : ['username=', 'password=', 'method=POST', 'url=http%3A%2F%2Ftwig-me.com%2Fv1%2Fusergroups%2FWKMUYXELA9LCC', 'jsondata=', 'submit=submit']
print("post_params : " + post_params)
params = post_params.split('&')
print("Params")
print(params)
# Initialize the key value pair dict
post_dict = {}
# Iterate on each param
for param in params:
# Each param would be like 'method=POST', etc
key_val = param.split('=')
print("Key Val :")
print(key_val)
key = key_val[0]
val = key_val[1]
# Update post_dict
post_dict[key] = val
return post_dict
# This web server takes care of the WiFi configuration
# max_run_sec
def web_server(max_run_sec = None):
# Turn wifi interface ON
turn_wifi_on()
# Create server socket
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
# TODO : If both the wifi and sta are operating simultaneously, then bind only to WiFi
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(addr)
s.listen(1)
# s.settimeout(1)
poller = select.poll()
poller.register(s, select.POLLIN)
# Get the current time since epoch
startTimeEpoch = utime.time()
while True:
events = poller.poll(200) # time in milliseconds
if events:
try:
gc.collect()
res = s.accept()
client_s = res[0]
client_addr = res[1]
req = ''
#while True:
# data = client_s.recv(200)
# if data:
# req += str(data, 'utf8')
# else:
# break
# utime.sleep_ms(50)
req = client_s.recv(4096)
req = req.decode()
print(req)
req = str(req)
# Came here means that there has been some connection!
# Reset the start time epoch in such a case:
startTimeEpoch = utime.time()
# Check route now
if req.find('configure.html') != -1:
print("Got configure request!\r\n")
# Check if the username and password are correct, if not, configure:
login_config = get_login_config()
username = login_config['user']
pwd = login_config['password']
print("Username : " + username + ", pwd : " + pwd)
# Find the POST PARAMETERS sent
# There would be just one entry in the array, so get the 0th index directly
# post_params : 'username=&password=&method=POST&url=http%3A%2F%2Ftwig-me.com%2Fv1%2Fusergroups%2FWKMUYXELA9LCC&jsondata=&submit=submit'
print("Came here A")
post_dict = get_post_params(req)
# Now check if the post_dict has the key and value for username and password as needed?
username_post = post_dict['username']
password_post = post_dict['password']
print("Came here B")
# Check if the password is same as expected
if (username_post == username) and (password_post == pwd):
hidden_input = '<input type="hidden" name="username" value="' + username + '"><input type="hidden" name="passphrase" value="' + pwd + '">'
# Send the login username and password inside the hidden input field
configure_html = "<!DOCTYPE html><html><head> <title>Ouroboros IoT WiFi Configuration Page</title> </head><body><form action=\"configure_wifi.html\" method=\"POST\">WiFi SSID : <input type=\"text\" name=\"essid\"></br>WiFi Password: <input type=\"password\" name=\"passphrase\" ></br>" + hidden_input + "<input type=\"submit\" value=\"submit\" name=\"submit\"></form></body></html>"
# TODO : Also show link to webpage, where from we can change the login credentials
client_s.send(configure_html)
else:
client_s.send(login_fail_html)
elif req.find('configure_wifi.html') != -1:
# Check if the username and password are correct, if not, configure:
login_config = get_login_config()
username = login_config['user']
pwd = login_config['password']
# Get post parameters
post_dict = get_post_params(req)
# Now check if the post_dict has the key and value for username and password as needed?
username_post = post_dict['username']
password_post = post_dict['password']
# Check if the password is same as expected
if (username_post == username) and (password_post == pwd):
# Do some sanity check for handling the new wifi ssid and password
new_wifi_ssid = post_dict['essid']
new_wifi_passphrase = post_dict['passphrase']
# Set the wifi credentials
save_wifi_config(new_wifi_ssid, new_wifi_passphrase)
client_s.send('<!DOCTYPE html><html><head> <title>Ouroboros IoT WiFi Configuration Success</title> </head><body>Configuration successful!<br>Device would go into reboot now!</body></html>')
# Reboot device now
machine.reset()
else:
client_s.send(login_fail_html)
elif req.find('index.html') != -1:
print("Got index.html request!\r\n")
client_s.send(html)
else :
# Do nothing
print("Invalid request received! Show the login page again!\r\n")
client_s.send(html)
client_s.close()
machine.idle()
except OSError:
# Got no request and it timedout!
print("Timed-out, no request received!\r\n")
except Exception as e:
print("Got some exception\r\n")
print(str(e))
finally:
if max_run_sec is not None:
elapsedTime = utime.time() - startTimeEpoch
if elapsedTime > max_run_sec:
# Max run time of web server has elapsed, time to exit this mode!
break
utime.sleep_ms()
machine.idle()
# When while loop ends!
s.close()
# Turn wifi interface OFF
turn_wifi_off()
# Starts a thread which runs the web server to handle WiFi
def start_web_server(max_run_sec = None):
# start_new_thread(web_server, (max_run_sec))
web_server(max_run_sec)
############# MAIN ##########################
# Initialize two pins to INPUT and OFF by default
init_pin(0)
init_pin(1)
#turn_wifi_off()
# Check if the home wifi network has been setup
# Check if home wifi config is valid, if so, connect to it
# If home wifi is not configured, then use the Web server all the time.
if get_wifi_config() is None:
# Came here means the wifi is not configured
# Start the web server
print("Starting web server")
start_web_server()
EDIT 1:
I'm able to setup WDT and feed it. So no more WDT reboots. However, POST issue is still there:
FYI, the following is the response:
POST /configure.html HTTP/1.1
Host: 192.168.0.1
Connection: keep-alive
Content-Length: 43
Cache-Control: max-age=0
Origin: http://192.168.0.1
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Linux; Android 5.1.1; Redmi Note 3 Build/LMY47V) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.123 Mobile Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://192.168.0.1/index.html
Accept-Encoding: g
As could be seen, the packet received is partial, the Content-Length header says 43 byte payload. But its not received. When using "nc", and running server locally, the packet received is follows:
POST /configure.html HTTP/1.1
Host: 192.168.0.1
Connection: keep-alive
Content-Length: 43
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/65.0.3325.181 Chrome/65.0.3325.181 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
username=admin&password=admin&submit=submit
Here, the 43 byte length payload could be easily seen.
So my question is, is the almost 800 byte payload too much to handle for ESP8266? Is there anything that could be done to remove the unnecessary headers that browser is sending? Any way to get all the data if its fragmented?
I faced a similar problem, my configuration is slightly different though.
I import my html from html_files.py as shown below.
cred_prompt = """
<!DOCTYPE html>
<html>
<head>
<title>ESP8266 connection</title>
</head>
<body>
<h2>
Enter the UID and Password to connect to WiFi
</h2>
<form action="/post">
uid: <input type="text" name="uid">
password: <input type="text" name="password">
<input type="submit" value="Submit">
</form><br>
</body>
</html>
"""
This is the function I use to get the credentials. I later save them into a file (Successive boots will use them)
def get_new_creds():
sta_if.disconnect()
print("Setting up webpage to get new credentials")
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
soc = socket.socket()
soc.bind(addr)
soc.listen(5)
print("Listening on", addr)
while True:
client, addr = soc.accept()
print("Client connected from", addr)
request = client.recv(1024)
request = request.decode().split()
uid, pwd = '', ''
if 'uid' in request[1]:
uid = request[1].split('&')[0].split('=')[1]
pwd = request[1].split('&')[1].split('=')[1]
write_new_creds(uid, pwd)
connect_to_wifi()
print("The UID is", uid, "and the Password is", pwd)
client.send('HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n')
client.send(html_files.connection_response.format(sta_if.ifconfig()[0]))
return uid, pwd
print(request)
client.send('HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n')
client.send(html_files.cred_prompt)
client.close()
This is the whole boot.py code if that helps.

CFNetwork SSLHandshake failed (-9807) on iOS simulator with localhost

I'm trying to connect openssl s_server and iOS client using TCP SSL, but get CFNetwork SSLHandshake failed (-9807).
Objective-C code(from here):
- (void)viewDidLoad {
[super viewDidLoad];
printf("method started \n");
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSData *iosTrustedCertDerData =
[NSData dataWithContentsOfFile:[bundle pathForResource:#"servercert"
ofType:#"der"]];
OSStatus err = noErr;
SecCertificateRef cert;
cert = SecCertificateCreateWithData(NULL, (CFDataRef) iosTrustedCertDerData);
assert(cert != NULL);
CFTypeRef result;
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
(id)kSecClassCertificate, kSecClass,
cert, kSecValueRef,
nil];
err = SecItemAdd((CFDictionaryRef)dict, &result);
assert(err == noErr || err == errSecDuplicateItem);
printf("adding finished \n");
if ((err == noErr) ||
(err == errSecDuplicateItem)) {
printf("success \n");
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL,
(CFStringRef)#"localhost",
1678,
&readStream,
&writeStream);
CFReadStreamSetProperty(readStream,
kCFStreamPropertySocketSecurityLevel,
kCFStreamSocketSecurityLevelTLSv1);
CFReadStreamOpen(readStream);
CFWriteStreamOpen(writeStream);
UInt8 buf[] = "Hello from iOS";
int bytesWritten = CFWriteStreamWrite(writeStream, buf, strlen((char*)buf));
} else {
printf("error!");
}
CFRelease(cert);
}
Sequence of commands to create the certificate and start the server (please pay attention to the 11 step: on the server side I use pem certificate and on the client side I use der certificate), file samples I got from this answer:
1.touch openssl-ca.cnf
2.Copy-pasted sample in openssl-ca.cnf. Only one line changed:
commonName_default = localhost
3.openssl req -x509 -config openssl-ca.cnf -newkey rsa:4096 -sha256 -nodes -out cacert.pem -outform PEM
4.touch openssl-server.cnf
5.Copy-pasted sample in openssl-server.cnf. Only two lines changed:
commonName_default = localhost
DNS.1 = localhost
6.openssl req -config openssl-server.cnf -newkey rsa:2048 -sha256 -nodes -out servercert.csr -outform PEM
7.Added 2 +1 sections in openssl-ca.cnf:
[ CA_default ]
...
base_dir = .
certificate = $base_dir/cacert.pem # The CA certifcate
private_key = $base_dir/cakey.pem # The CA private key
new_certs_dir = $base_dir # Location for new certs after signing
database = $base_dir/index.txt # Database index file
serial = $base_dir/serial.txt # The current serial number
unique_subject = no # Set to 'no' to allow creation of
# several certificates with same subject.
...
####################################################################
[ signing_policy ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
####################################################################
[ signing_req ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
8.touch index.txt
9.echo '01' > serial.txt
10.openssl ca -config openssl-ca.cnf -policy signing_policy -extensions signing_req -out servercert.pem -infiles servercert.csr
11.openssl x509 -in servercert.pem -inform PEM -out servercert.der -outform DER
12.Added servercert.der in iOS project
13.let sslsock = SSLSocketLite(inHost: "localhost", inPort: 1678)
14.Exception Domains -> +localhost
15.openssl s_server -key serverkey.pem -cert servercert.pem -accept 1678
Final version of openssl-ca.cnf:
HOME = .
RANDFILE = $ENV::HOME/.rnd
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
[ CA_default ]
default_days = 1000 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = sha256 # use public key default MD
preserve = no # keep passed DN ordering
x509_extensions = ca_extensions # The extensions to add to the cert
email_in_dn = no # Don't concat the email in the DN
copy_extensions = copy # Required to copy SANs from CSR to cert
base_dir = .
certificate = $base_dir/cacert.pem # The CA certifcate
private_key = $base_dir/cakey.pem # The CA private key
new_certs_dir = $base_dir # Location for new certs after signing
database = $base_dir/index.txt # Database index file
serial = $base_dir/serial.txt # The current serial number
unique_subject = no # Set to 'no' to allow creation of
# several certificates with same subject.
####################################################################
[ req ]
default_bits = 4096
default_keyfile = cakey.pem
distinguished_name = ca_distinguished_name
x509_extensions = ca_extensions
string_mask = utf8only
####################################################################
[ ca_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Maryland
localityName = Locality Name (eg, city)
localityName_default = Baltimore
organizationName = Organization Name (eg, company)
organizationName_default = Test CA, Limited
organizationalUnitName = Organizational Unit (eg, division)
organizationalUnitName_default = Server Research Department
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = localhost
emailAddress = Email Address
emailAddress_default = test#example.com
####################################################################
[ ca_extensions ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always, issuer
basicConstraints = critical, CA:true
keyUsage = keyCertSign, cRLSign
####################################################################
[ signing_policy ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
####################################################################
[ signing_req ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
Final version of openssl-server.cnf:
HOME = .
RANDFILE = $ENV::HOME/.rnd
####################################################################
[ req ]
default_bits = 2048
default_keyfile = serverkey.pem
distinguished_name = server_distinguished_name
req_extensions = server_req_extensions
string_mask = utf8only
####################################################################
[ server_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = MD
localityName = Locality Name (eg, city)
localityName_default = Baltimore
organizationName = Organization Name (eg, company)
organizationName_default = Test CA, Limited
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = localhost
emailAddress = Email Address
emailAddress_default = test#example.com
####################################################################
[ server_req_extensions ]
subjectKeyIdentifier = hash
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
subjectAltName = #alternate_names
nsComment = "OpenSSL Generated Certificate"
####################################################################
[ alternate_names ]
DNS.1 = localhost
iOS output:
method started
adding finished
success
2016-08-30 19:17:06.619
ssltest[5418:141544] CFNetwork SSLHandshake failed (-9807)
OpenSSL s_server output(nothing happened):
Using default temp DH parameters
ACCEPT
What have I missed? And how can I solve it?
Maybe someone can share working cert with the localhost address in the commonName? Using this I will understand which exactly is the problem: cert and my pem to der converting or iOS app.

How to configure a freeradius server to require NAS-IP-Address attribute?

I want to configure a freeradius server in the way that an authentication is successful only if NAS-IP-Address attribute is not empty and equals to some specific IP (of course a user name and a password match).
How should I do it? I have tried to read the documentation without success:
http://freeradius.org/rfc/attributes.html
http://freeradius.org/rfc/rfc2865.html#NAS-IP-Address
Sure, there are many ways of doing this.
authorize {
if (!NAS-IP-Address) {
reject
}
if (NAS-IP-Address != 192.168.0.2) {
reject
}
if ("%{sql:SELECT count(*) FROM table WHERE User-Name = '%{User-Name}' AND IP-Address = '%{NAS-IP-Address}'" == 0) {
reject
}
}
In v3.0.x subnet matching is also supported, where < > are reassigned to mean the set operators (< subset of) (> superset of).
if (!(<ipv4prefix>NAS-IP-Address < 192.168.0.0/16)) {
reject
}
NAS-IP-Address = 192.168.0.2
(0) ? if (<ipv4prefix>NAS-IP-Address < 192.168.0.0/16)
(0) ? if (<ipv4prefix>NAS-IP-Address < 192.168.0.0/16) -> TRUE
NAS-IP-Address = 192.169.0.2
(0) ? if (<ipv4prefix>NAS-IP-Address < 192.168.0.0/16)
(0) ? if (<ipv4prefix>NAS-IP-Address < 192.168.0.0/16) -> FALSE

Resources