Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
O
OpnSense
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kulya
OpnSense
Commits
d7e2c665
Commit
d7e2c665
authored
Oct 13, 2015
by
Ad Schellevis
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
(captiveportal, new) work in progress backend scripts
parent
cca3be68
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
71 additions
and
20 deletions
+71
-20
cp-background-process.py
...e/scripts/OPNsense/CaptivePortal/cp-background-process.py
+35
-18
db.py
src/opnsense/scripts/OPNsense/CaptivePortal/lib/db.py
+36
-2
No files found.
src/opnsense/scripts/OPNsense/CaptivePortal/cp-background-process.py
View file @
d7e2c665
...
...
@@ -40,7 +40,8 @@ from lib.ipfw import IPFW
from
lib.daemonize
import
Daemonize
def
main
():
syslog
.
syslog
(
syslog
.
LOG_ERR
,
'starting captiveportal background process'
)
syslog
.
openlog
(
'captiveportal'
,
logoption
=
syslog
.
LOG_DAEMON
)
syslog
.
syslog
(
syslog
.
LOG_NOTICE
,
'starting captiveportal background process'
)
# handle to ipfw, arp and the config
ipfw
=
IPFW
()
arp
=
ARP
()
...
...
@@ -60,6 +61,8 @@ def main():
registered_addresses
=
ipfw
.
list_table
(
zoneid
)
registered_add_accounting
=
ipfw
.
list_accounting_info
()
expected_clients
=
db
.
list_clients
(
zoneid
)
concurrent_users
=
db
.
find_concurrent_user_sessions
(
zoneid
)
# handle connected clients, timeouts, address changes, etc.
for
db_client
in
expected_clients
:
# fetch ip address (or network) from database
...
...
@@ -67,25 +70,36 @@ def main():
# there are different reasons why a session should be removed, check for all reasons and
# use the same method for the actual removal
drop_session
=
False
# todo, static ip and addresses shouldn't be affected by the timeout rules below.
# check if hardtimeout is set and overrun for this session
if
'hardtimeout'
in
cpzones
[
zoneid
]
and
str
(
cpzones
[
zoneid
][
'hardtimeout'
])
.
isdigit
():
# hardtimeout should be set and we should have collected some session data from the client
if
int
(
cpzones
[
zoneid
][
'hardtimeout'
])
>
0
and
float
(
db_client
[
'startTime'
])
>
0
:
if
(
time
.
time
()
-
float
(
db_client
[
'startTime'
]))
/
60
>
int
(
cpzones
[
zoneid
][
'hardtimeout'
]):
drop_session
=
True
# check if idletimeout is set and overrun for this session
if
'idletimeout'
in
cpzones
[
zoneid
]
and
str
(
cpzones
[
zoneid
][
'idletimeout'
])
.
isdigit
():
# idletimeout should be set and we should have collected some session data from the client
if
int
(
cpzones
[
zoneid
][
'idletimeout'
])
>
0
and
float
(
db_client
[
'last_accessed'
])
>
0
:
if
(
time
.
time
()
-
float
(
db_client
[
'last_accessed'
]))
/
60
>
int
(
cpzones
[
zoneid
][
'idletimeout'
]):
drop_session
=
True
drop_session_reason
=
None
# session cleanups, only for users not for static hosts/ranges.
if
db_client
[
'userName'
]
!=
''
:
# check if hardtimeout is set and overrun for this session
if
'hardtimeout'
in
cpzones
[
zoneid
]
and
str
(
cpzones
[
zoneid
][
'hardtimeout'
])
.
isdigit
():
# hardtimeout should be set and we should have collected some session data from the client
if
int
(
cpzones
[
zoneid
][
'hardtimeout'
])
>
0
and
float
(
db_client
[
'startTime'
])
>
0
:
if
(
time
.
time
()
-
float
(
db_client
[
'startTime'
]))
/
60
>
int
(
cpzones
[
zoneid
][
'hardtimeout'
]):
drop_session_reason
=
"session
%
s hit hardtimeout"
%
db_client
[
'sessionId'
]
# check if idletimeout is set and overrun for this session
if
'idletimeout'
in
cpzones
[
zoneid
]
and
str
(
cpzones
[
zoneid
][
'idletimeout'
])
.
isdigit
():
# idletimeout should be set and we should have collected some session data from the client
if
int
(
cpzones
[
zoneid
][
'idletimeout'
])
>
0
and
float
(
db_client
[
'last_accessed'
])
>
0
:
if
(
time
.
time
()
-
float
(
db_client
[
'last_accessed'
]))
/
60
>
int
(
cpzones
[
zoneid
][
'idletimeout'
]):
drop_session_reason
=
"session
%
s hit idletimeout"
%
db_client
[
'sessionId'
]
# cleanup concurrent users
if
'concurrentlogins'
in
cpzones
[
zoneid
]
and
int
(
cpzones
[
zoneid
][
'concurrentlogins'
])
==
0
:
if
db_client
[
'sessionId'
]
in
concurrent_users
:
drop_session_reason
=
"remove concurrent session
%
s"
%
db_client
[
'sessionId'
]
# if mac address changes, drop session. it's not the same client
current_arp
=
arp
.
get_by_ipaddress
(
db_client
[
'ipAddress'
])
if
current_arp
is
not
None
and
current_arp
[
'mac'
]
!=
db_client
[
'macAddress'
]:
drop_session_reason
=
"mac address changed for session
%
s"
%
db_client
[
'sessionId'
]
# check session, if it should be active, validate its properties
if
not
drop_session
:
if
drop_session_reason
is
None
:
# registered client, but not active according to ipfw (after reboot)
if
cpnet
not
in
registered_addresses
:
ipfw
.
add_to_table
(
zoneid
,
cpnet
)
...
...
@@ -95,6 +109,7 @@ def main():
ipfw
.
add_accounting
(
cpnet
)
else
:
# remove session
syslog
.
syslog
(
syslog
.
LOG_NOTICE
,
drop_session_reason
)
db
.
del_client
(
zoneid
,
db_client
[
'sessionId'
])
ipfw
.
delete_from_table
(
zoneid
,
cpnet
)
ipfw
.
del_accounting
(
cpnet
)
...
...
@@ -110,6 +125,8 @@ def main():
break
except
:
syslog
.
syslog
(
syslog
.
LOG_ERR
,
traceback
.
format_exc
())
print
(
traceback
.
format_exc
())
break
# startup
if
len
(
sys
.
argv
)
>
1
and
sys
.
argv
[
1
]
.
strip
()
.
lower
()
==
'run'
:
...
...
src/opnsense/scripts/OPNsense/CaptivePortal/lib/db.py
View file @
d7e2c665
...
...
@@ -143,12 +143,18 @@ class DB(object):
, CASE WHEN si.packets_out IS NULL THEN 0 ELSE si.packets_out END packets_out
, CASE WHEN si.bytes_in IS NULL THEN 0 ELSE si.bytes_in END bytes_in
, CASE WHEN si.bytes_out IS NULL THEN 0 ELSE si.bytes_out END bytes_out
, CASE WHEN si.last_accessed IS NULL THEN cc.created ELSE si.last_accessed END last_accessed
, CASE WHEN si.last_accessed IS NULL OR si.last_accessed =0
THEN cc.created
ELSE si.last_accessed
END last_accessed
FROM cp_clients cc
LEFT JOIN session_info si ON si.zoneid = cc.zoneid AND si.sessionid = cc.sessionid
WHERE cc.zoneid = :zoneid
AND cc.deleted = 0
order by case when cc.username is not null then cc.username else cc.ip_address end
, cc.created desc
"""
,
{
'zoneid'
:
zoneid
})
while
True
:
# fetch field names
if
len
(
fieldnames
)
==
0
:
...
...
@@ -162,10 +168,38 @@ class DB(object):
record
=
dict
()
for
idx
in
range
(
len
(
row
)):
record
[
fieldnames
[
idx
]]
=
row
[
idx
]
result
.
append
(
record
)
return
result
def
find_concurrent_user_sessions
(
self
,
zoneid
):
""" query zone database for concurrent user sessions
:param zoneid: zone id
:return: dictionary containing duplicate sessions
"""
result
=
dict
()
cur
=
self
.
_connection
.
cursor
()
# rename fields for API
cur
.
execute
(
""" SELECT cc.sessionid sessionId
, cc.username userName
FROM cp_clients cc
WHERE cc.zoneid = :zoneid
AND cc.deleted = 0
AND cc.username is not null
and cc.username <> ""
order by case when cc.username is not null then cc.username else cc.ip_address end
, cc.created desc
"""
,
{
'zoneid'
:
zoneid
})
prev_user
=
None
while
True
:
row
=
cur
.
fetchone
()
if
row
is
None
:
break
elif
prev_user
is
not
None
and
prev_user
==
row
[
1
]:
result
[
row
[
0
]]
=
row
[
1
]
prev_user
=
row
[
1
]
return
result
def
update_accounting_info
(
self
,
details
):
""" update internal accounting database with given ipfw info (not per zone)
:param details: ipfw accounting details
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment