diff --git a/docs/sql/README.rst b/docs/sql/README.rst index 849e4f1c..08d75c8c 100644 --- a/docs/sql/README.rst +++ b/docs/sql/README.rst @@ -12,14 +12,9 @@ MySQL Installation On your Cowrie server, run:: - $ sudo apt-get install libmysqlclient-dev python-mysqldb $ su - cowrie $ source cowrie/cowrie-env/bin/activate - $ pip install mysqlclient - -Previously MySQL-python was used. Only if you run into isses with mysqlclient, try this instead:: - - $ pip install MySQL-python + $ pip install mysql-connector-python MySQL Configuration =================== diff --git a/requirements-output.txt b/requirements-output.txt index e3dc667b..4610dd06 100644 --- a/requirements-output.txt +++ b/requirements-output.txt @@ -12,9 +12,7 @@ elasticsearch==7.12.0 hpfeeds3==0.9.10 # mysql -# If this fails, see documentation /home/cowrie/cowrie/docs/sql/README.md -# There are two options, mysqlclient is newer and provides Python3 support. -mysqlclient==2.0.3 +mysql-connector-python==8.0.25 # mongodb pymongo==3.11.3 diff --git a/src/cowrie/output/mysql.py b/src/cowrie/output/mysql.py index dfabbc2b..b6439b0f 100644 --- a/src/cowrie/output/mysql.py +++ b/src/cowrie/output/mysql.py @@ -2,9 +2,6 @@ MySQL output connector. Writes audit logs to MySQL database """ - -import MySQLdb - from twisted.enterprise import adbapi from twisted.internet import defer from twisted.python import log @@ -12,6 +9,9 @@ from twisted.python import log import cowrie.core.output from cowrie.core.config import CowrieConfig +# For exceptions: https://dev.mysql.com/doc/connector-python/en/connector-python-api-errors-error.html +import mysql.connector + class ReconnectingConnectionPool(adbapi.ConnectionPool): """ @@ -22,6 +22,11 @@ class ReconnectingConnectionPool(adbapi.ConnectionPool): by checking exceptions by error code and only disconnecting the current connection instead of all of them. + CR_CONN_HOST_ERROR: 2003: Cant connect to MySQL server on server (10061) + CR_SERVER_GONE_ERROR: 2006: MySQL server has gone away + CR_SERVER_LOST 2013: Lost connection to MySQL server + ER_LOCK_DEADLOCK 1213: Deadlock found when trying to get lock) + Also see: http://twistedmatrix.com/pipermail/twisted-python/2009-July/020007.html """ @@ -29,10 +34,17 @@ class ReconnectingConnectionPool(adbapi.ConnectionPool): def _runInteraction(self, interaction, *args, **kw): try: return adbapi.ConnectionPool._runInteraction(self, interaction, *args, **kw) - except (MySQLdb.OperationalError, MySQLdb._exceptions.OperationalError) as e: - if e.args[0] not in (2003, 2006, 2013): + except mysql.connector.Error as e: + # except (MySQLdb.OperationalError, MySQLdb._exceptions.OperationalError) as e: + if e.errno not in ( + mysql.connector.errorcode.CR_CONN_HOST_ERROR, + mysql.connector.errorcode.CR_SERVER_GONE_ERROR, + mysql.connector.errorcode.CR_SERVER_LOST, + mysql.connector.errorcode.ER_LOCK_DEADLOCK, + ): raise e - log.msg(f"RCP: got error {e}, retrying operation") + + log.msg(f"output_mysql: got error {e!r}, retrying operation") conn = self.connections.get(self.threadID()) self.disconnect(conn) # Try the interaction again @@ -41,7 +53,7 @@ class ReconnectingConnectionPool(adbapi.ConnectionPool): class Output(cowrie.core.output.Output): """ - mysql output + MySQL output """ db = None @@ -52,7 +64,7 @@ class Output(cowrie.core.output.Output): port = CowrieConfig.getint("output_mysql", "port", fallback=3306) try: self.db = ReconnectingConnectionPool( - "MySQLdb", + "mysql.connector", host=CowrieConfig.get("output_mysql", "host"), db=CowrieConfig.get("output_mysql", "database"), user=CowrieConfig.get("output_mysql", "username"), @@ -64,11 +76,11 @@ class Output(cowrie.core.output.Output): cp_reconnect=True, use_unicode=True, ) - except (MySQLdb.Error, MySQLdb._exceptions.Error) as e: + # except (MySQLdb.Error, MySQLdb._exceptions.Error) as e: + except Exception as e: log.msg(f"output_mysql: Error {e.args[0]}: {e.args[1]}") def stop(self): - self.db.commit() self.db.close() def sqlerror(self, error): @@ -78,7 +90,7 @@ class Output(cowrie.core.output.Output): """ if error.value.args[0] in (1146, 1406): log.msg(f"output_mysql: MySQL Error: {error.value.args!r}") - log.msg("MySQL schema maybe misconfigured, doublecheck database!") + log.msg("output_mysql: MySQL schema maybe misconfigured, doublecheck database!") else: log.msg(f"output_mysql: MySQL Error: {error.value.args!r}") @@ -94,15 +106,19 @@ class Output(cowrie.core.output.Output): @defer.inlineCallbacks def write(self, entry): if entry["eventid"] == "cowrie.session.connect": + if self.debug: + log.msg(f"output_mysql: SELECT `id` FROM `sensors` WHERE `ip` = '{self.sensor}'") r = yield self.db.runQuery( - "SELECT `id`" "FROM `sensors`" f"WHERE `ip` = {self.sensor}" + f"SELECT `id` FROM `sensors` WHERE `ip` = '{self.sensor}'" ) if r: sensorid = r[0][0] else: + if self.debug: + log.msg(f"output_mysql: INSERT INTO `sensors` (`ip`) VALUES ('{self.sensor}')") yield self.db.runQuery( - "INSERT INTO `sensors` (`ip`) " f"VALUES ({self.sensor})" + f"INSERT INTO `sensors` (`ip`) VALUES ('{self.sensor}')" ) r = yield self.db.runQuery("SELECT LAST_INSERT_ID()")