1
0
mirror of https://github.com/pavel-odintsov/fastnetmon synced 2024-09-22 14:01:20 +02:00

Merge pull request #537 from ericchou1/master

Add A10 Plugin
This commit is contained in:
Pavel Odintsov 2016-07-27 10:16:05 +03:00 committed by GitHub
commit cb459556ac
13 changed files with 334 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.pyc
__pycache__
*.DS_Store

5
src/a10_plugin/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
*.py
*.python
*.egg
*.egg-info/

68
src/a10_plugin/README.md Normal file
View File

@ -0,0 +1,68 @@
Fastnetmon Plugin: A10 Networks TPS AXAPIv3 integration for FastNetMon
This script connect to A10 TPS device to create Protected Object and announce BGP route toward upstream router upon FastNetMon ban detection.
1. Place both Python files at a directory that is reachable by FastNetMon
2. Make sure both scripts are executable, i.e. "chmod +x a10.py fastnetmon_a10_v0.2.py"
3. Modify fastnetmon.conf for notification, i.e. notify_script_path = <path>/fastnetmon_a10_v0.2.py
Please modify the following:
1. A10 mitigator IP
2. BGP Autonomous System Number
3. Username and Password for your A10 Device. Note that you can use your own password vault or protection schema
For more information about A10 Networks AXAPIv3:
https://www.a10networks.com/resources/glossary/axapi-custom-management
v0.2 - Jul 7th, 2016 - initial commit
Author: Eric Chou ericc@a10networks.com
Feedback and Feature Requests are Welcomed.
Example Usage:
- Ban action:
```
a10-ubuntu3:~/fastnetmon/src/a10_plugin$ sudo python fastnetmon_a10_v0.2.py "10.10.10.10" "outgoing" "111111" "ban"
TH4435-1#show ddos dst zone all-entries
Legend (Rate/Limit): 'U'nlimited, 'E'xceeded, '-' Not applicable
Legend (State) : 'W'hitelisted, 'B'lacklisted, 'P'ermitted, black'H'oled, 'I'dle, 'L'earning, 'M'onitoring, '-' Regular mode
Zone Name / Zone Service Info | [State]| Curr Conn| Conn Rate| Pkt Rate | kBit Rate|Frag Pkt R|Sources # |Age |LockU
| | Limit| Limit| Limit| Limit| Limit| Limit|#min| Time
-----------------------------------------------------------------------------------------------------------------------------------
10.10.10.10_zone [M] U U U U U 1S 0
- U U U U U
Displayed Entries: 1
Displayed Services: 0
TH4435-1#sh run router bgp
!Section configuration: 221 bytes
!
router bgp 64513
<skip>
network 10.10.10.10/32
<skip>
!
TH4435-1#
TH4435-1#sh run router bgp | i 10.10.10.10
network 10.10.10.10/32
TH4435-1#
```
- Unban action:
a10-ubuntu3:~/fastnetmon/src/a10_plugin$ sudo python fastnetmon_a10_v0.2.py "10.10.10.10" "outgoing" "111111" "unban"
```
TH4435-1#sh run router bgp | i 10.10.10.10
TH4435-1#
```

43
src/a10_plugin/a10.py Executable file
View File

@ -0,0 +1,43 @@
#
# v0.1
# ericc@a10networks.com
#
import json, urllib2
def axapi_auth(host, username, password):
base_uri = 'https://'+host
auth_payload = {"credentials": {"username": username, "password": password}}
r = axapi_action(base_uri + '/axapi/v3/auth', payload=auth_payload)
signature = json.loads(r)['authresponse']['signature']
return base_uri, signature
def axapi_action(uri, payload='', signature='', method='POST'):
try:
if method == 'POST':
req = urllib2.Request(uri)
req.add_header('content-type', 'application/json')
if signature:
req.add_header('Authorization', 'A10 {0}'.format(signature))
response = urllib2.urlopen(req, json.dumps(payload))
elif method == 'GET':
req = urllib2.Request(uri)
req.add_header('content-type', 'application/json')
if signature:
req.add_header('Authorization', 'A10 {0}'.format(signature))
response = urllib2.urlopen(req)
elif method == 'DELETE':
req = urllib2.Request(uri)
req.add_header('content-type', 'application/json')
req.get_method = lambda: 'DELETE'
if signature:
req.add_header('Authorization', 'A10 {0}'.format(signature))
response = urllib2.urlopen(req)
return response.read()
except Exception as e:
raise

View File

@ -0,0 +1,14 @@
!
ddos dst zone Test-Server
ip 210.0.0.10
operational-mode monitor
port 53 udp
level 0
zone-escalation-score 1
indicator pkt-rate
score 50
zone-threshold 1
zone-violation-actions bmf_a10_script
level 1
!

View File

@ -0,0 +1,94 @@
#!/usr/bin/python
#
# v0.2 created [ban | unban] [on ramp | off ramp action] for A10 TPS
# v0.3 offload URI path and json_body into separate json_config files
# Eric Chou (ericc@a10networks.com)
#
import sys
from sys import stdin
import optparse
import logging, json
from a10 import axapi_auth, axapi_action
from json_config.logoff import logoff_path
from json_config.write_memory import write_mem_path
from json_config.ddos_dst_zone import ddos_dst_zone_path, ddos_dst_zone
from json_config.bgp import bgp_advertisement_path, bgp_advertisement
LOG_FILE = "/var/log/fastnetmon-notify.log"
logger = logging.getLogger("DaemonLog")
logger.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler = logging.FileHandler(LOG_FILE)
handler.setFormatter(formatter)
logger.addHandler(handler)
client_ip_as_string=sys.argv[1]
data_direction=sys.argv[2]
pps_as_string=int(sys.argv[3])
action=sys.argv[4]
logger.info(" - " . join(sys.argv))
# A10 Mitigator Information
mitigator_ip = "192.168.199.152"
zone_name = client_ip_as_string + "_zone"
ip_addr = client_ip_as_string
asn="65003"
mitigator_base_url, signature = axapi_auth(mitigator_ip, "admin", "a10")
if action == "unban":
try:
r = axapi_action(mitigator_base_url+'/axapi/v3/router/bgp/'+asn+'/network/ip-cidr/172.31.201.2%2F32', method="DELETE", signature=signature)
except Exception as e:
logger.info("route not removed in unban, returned: " + str(e))
# Commit config
axapi_action(mitigator_base_url+write_mem_path, signature=signature)
# Logoff
axapi_action(mitigator_base_url+logoff_path, signature=signature)
sys.exit(0)
elif action == "ban" or action == "attack_details":
r = axapi_action(mitigator_base_url+ddos_dst_zone_path, method='GET', signature=signature)
if zone_name in [i['zone-name'] for i in json.loads(r)['zone-list']]:
r = axapi_action(mitigator_base_url+ddos_dst_zone_path+zone_name, method="DELETE", signature=signature)
logger.info(str(r))
# A10 Mitigation On Ramp
zone_name = client_ip_as_string + "_zone"
ip_addr = client_ip_as_string
returned_body = ddos_dst_zone(zone_name, ip_addr)
try:
r = axapi_action(mitigator_base_url+ddos_dst_zone_path, signature=signature, payload=returned_body)
except Exception as e:
logger("zone not created: " + str(e))
route_advertisement = bgp_advertisement(ip_addr)
try:
r = axapi_action(mitigator_base_url+bgp_advertisement_path+asn, payload=route_advertisement, signature=signature)
except Exception as e:
logger("route not added: " + str(e))
# Commit changes
axapi_action(mitigator_base_url+write_mem_path, signature=signature)
# Log off
axapi_action(mitigator_base_url+logoff_path, signature=signature)
sys.exit(0)
else:
sys.exit(0)

View File

View File

@ -0,0 +1,16 @@
bgp_advertisement_path = '/axapi/v3/router/bgp/'
def bgp_advertisement(ip_addr):
route_advertisement = {
"bgp":
{
"network": {
"ip-cidr-list": [
{
"network-ipv4-cidr":ip_addr+"/32",
}
]
},
}
}
return route_advertisement

View File

@ -0,0 +1,44 @@
ddos_dst_zone_path = '/axapi/v3/ddos/dst/zone/'
def ddos_dst_zone(zone_name, ip_addr):
port_num = 53
port_protocol = 'udp'
ddos_dst_zone_payload = {
"zone-list": [
{
"zone-name":zone_name,
"ip": [
{
"ip-addr":ip_addr
}
],
"operational-mode":"monitor",
"port": {
"zone-service-list": [
{
"port-num":port_num,
"protocol":port_protocol,
"level-list": [
{
"level-num":"0",
"zone-escalation-score":1,
"indicator-list": [
{
"type":"pkt-rate",
"score":50,
"zone-threshold-num":1,
}
],
},
{
"level-num":"1",
}
],
}
],
},
}
]
}
return ddos_dst_zone_payload

View File

@ -0,0 +1,3 @@
logoff_path = '/axapi/v3/logoff'

View File

@ -0,0 +1 @@
write_mem_path = '/axapi/v3/write/memory'

View File

View File

@ -0,0 +1,43 @@
import unittest,sys
sys.path.append('../')
from a10 import axapi_auth, axapi_action
a10_tps = "192.168.199.152"
username = "admin"
password = "a10"
hostname = "TH4435"
class Test_Auth(unittest.TestCase):
def testAssertTrue(self):
print("Testing axapi_auth")
try:
mitigator_base_url, signature = axapi_auth(a10_tps, username, password)
print("base url: ", mitigator_base_url, "Signature: ", signature)
axapi_action(mitigator_base_url+"/axapi/v3/logoff")
except Exception as e:
self.fail("Not authenticated")
class Test_API_Actions(unittest.TestCase):
def testAssertTrue(self):
try:
print("Testing GET")
mitigator_base_url, signature = axapi_auth(a10_tps, username, password)
r = axapi_action(mitigator_base_url+"/axapi/v3/version/oper", method='GET', signature=signature)
print(str(r))
print("Testing POST")
hostname_payload = {"hostname": {"value": hostname}}
r = axapi_action(mitigator_base_url+"/axapi/v3/hostname", payload=hostname_payload, signature=signature)
print(str(r))
axapi_action(mitigator_base_url+"/axapi/v3/logoff")
except Exception as e:
self.fail("Failed")
if __name__ == "__main__":
unittest.main()