OSS::IPAddress SIPWebSocketConnection::getRemoteAddress() const /// Returns the last read source address { if (_lastReadAddress.isValid()) return _lastReadAddress; if (_pServerConnection) { boost::system::error_code ec; EndPoint ep = _pServerConnection->get_raw_socket().remote_endpoint(ec); if (!ec) { boost::asio::ip::address ip = ep.address(); _lastReadAddress = OSS::IPAddress(ip.to_string(), ep.port()); return _lastReadAddress; } else { OSS_LOG_WARNING("SIPWebSocketConnection::getRemoteAddress() Exception " << ec.message()); return _connectAddress; } } return OSS::IPAddress(); }
int DTLSBio::sslRead(char* buf, int bufLen) { /// 1. Read available data from the external input (probably libnice) /// If packet is not a DTLS packet, return the read value, else goto 2 /// 2. Store (encrypted) read data into the input BIO using BIO_write /// 3. Call SSL_read to decrypt the data /// Returns return value of SSL_read /// if (!_pSSL) { OSS_LOG_ERROR("DTLSBio::sslRead - _pSSL is not set."); return 0; } if (!SSL_is_init_finished(_pSSL)) { OSS_LOG_ERROR("DTLSBio::sslRead - SSL Handshake is not yet completed."); return 0; } int ret = 0; char readBuf[DTLS_BIO_BUFFER_LEN]; ret = readDirect(readBuf, DTLS_BIO_BUFFER_LEN); if (ret > 0) { // // We have read some packets // if (DTLSSession::peek(readBuf) != DTLSSession::DTLS) { // // Not a DTLS packet. return the raw packet // if (ret > bufLen) { // // We have read a packet that is bigger than the buffer provided // we do not have any better option but to truncate // OSS_LOG_WARNING("DTLSBio::sslRead - buffer size is smaller than the packet in the buffer. Packet will be truncated!"); ret = bufLen; } memcpy(buf, readBuf, ret); return ret; } ret = BIO_write(_pInBIO, readBuf, ret); if (ret > 0) { // // Packets are written to the IN BIO. Read it back unencrypted. // ret = SSL_read(_pSSL, buf, bufLen); } } return ret; }
OSS::IPAddress SIPWebSocketConnection::getLocalAddress() const /// Returns the local address binding for this transport { if (_localAddress.isValid()) return _localAddress; if (_pServerConnection) { boost::system::error_code ec; EndPoint ep = _pServerConnection->get_raw_socket().local_endpoint(ec); if (!ec) { boost::asio::ip::address ip = ep.address(); _localAddress = OSS::IPAddress(ip.to_string(), ep.port()); return _localAddress; } else { OSS_LOG_WARNING("SIPWebSocketConnection::getLocalAddress() Exception " << ec.message()); } } return OSS::IPAddress(); }
void SIPWebSocketConnection::handleRead(const boost::system::error_code& e, std::size_t bytes_transferred, OSS_HANDLE userData) /// Handle completion of a read operation. { if (e || bytes_transferred <=0) { OSS_LOG_DEBUG("SIPWebSocketConnection::handleRead Exception " << e.message()); if (++_readExceptionCount >= 5) { OSS_LOG_ERROR("SIPWebSocketConnection::handleRead has reached maximum exception count. Bailing out."); boost::system::error_code ignored_ec; _connectionManager.stop(shared_from_this()); } } OSS_LOG_DEBUG("SIPWebSocketConnection::handleRead STARTING new connection"); std::string* buffer = reinterpret_cast<std::string*>(userData); // // set the last read address // if (!_lastReadAddress.isValid()) { boost::system::error_code ec; EndPoint ep = _pServerConnection->get_raw_socket().remote_endpoint(ec); if (!ec) { boost::asio::ip::address ip = ep.address(); _lastReadAddress = OSS::IPAddress(ip.to_string(), ep.port()); } else { OSS_LOG_WARNING("SIPWebSocketConnection::handleRead() Exception " << ec.message()); } } // // Reset the read exception count // _readExceptionCount = 0; _bytesRead = bytes_transferred; if (!_pRequest) { _pRequest = SIPMessage::Ptr(new SIPMessage()); } boost::tribool result; const char* begin = buffer->data(); const char* end = buffer->data() + bytes_transferred; boost::tuple<boost::tribool, const char*> ret = _pRequest->consume(begin, end); result = ret.get<0>(); const char* tail = ret.get<1>(); if (result) { // // Message has been read in full // _pDispatch->onReceivedMessage(_pRequest->shared_from_this(), shared_from_this()); if (tail >= end) { // // The end of the SIPMessage is reached so we can simply reset the // request buffer and start the read operation all over again // _pRequest.reset(); // // We are done // return; } else { // // This should not happen as there is one full message per read. // The tail is within the range of the end of the read buffer. // OSS_ASSERT(false); } } else if (!result) { _pRequest.reset(); } else { // // This should not happen as there is one full message per read. // Partial message? // OSS_ASSERT(false); } }
void AccessControl::logPacket(const boost::asio::ip::address& source, std::size_t bytesRead, ViolationReport* pReport) { /**************************************************************************** * The packet rate ratio allows the transport to detect a potential DoS * * attack. It works by detecting the packet read rate per second as * * designated by the upper limit. If the value of packet rate is 50/100, * * the maximum packet rate before the SBC raises the alert level if a * * potential denial of service attack is 100 packets per second. * * When this happens, the transport layer checks if there is a particular * * IP that is sending more than its allowable rate of 50 packets per second.* * If the sender is violating the threshold, it will be banned for 1 hour * * which is the third parameter of 3600 seconds. * ****************************************************************************/ if (!_enabled) return; _packetCounterMutex.lock(); std::map<boost::asio::ip::address, unsigned int>::iterator iter = _packetCounter.find(source); if (iter != _packetCounter.end()) _packetCounter[source] = ++iter->second; else _packetCounter[source] = 1; if (++_currentIterationCount >= _packetsPerSecondThreshold) { boost::posix_time::ptime now(boost::posix_time::microsec_clock::local_time()); int currentCount = _currentIterationCount; _currentIterationCount = 0; boost::posix_time::time_duration timeDiff = now - _lastTime; if (timeDiff.total_milliseconds() <= 1000) { // // We got a ratelimit violation // OSS_LOG_WARNING("ALERT: Threshold Violation Detected. Rate " << currentCount << " >= " << _packetsPerSecondThreshold); if (pReport) pReport->thresholdViolated = true; std::size_t watermark = 0; boost::asio::ip::address suspect; for (std::map<boost::asio::ip::address, unsigned int>::iterator iter = _packetCounter.begin(); iter != _packetCounter.end(); iter++) { if (iter->second > watermark) { watermark = iter->second; suspect = iter->first; if (watermark >= _thresholdViolationRate && _autoBanThresholdViolators ) { if (!isWhiteListed(suspect)) { OSS_LOG_WARNING("ALERT: Threshold Violator Address = " << suspect.to_string() << " Packets sent within the last second is " << watermark << ". Violator is now in jail for a maximum of " << _banLifeTime << " seconds."); banAddress(suspect); if (pReport) pReport->violators.push_back(suspect.to_string()); } else { OSS_LOG_WARNING("ALERT: Threshold Violator Address = " << suspect.to_string() << " Packets sent within the last second is " << watermark << ". Violator is TRUSTED and will be allowed to bombard."); } } else if (watermark >= _thresholdViolationRate && !_autoBanThresholdViolators ) { OSS_LOG_WARNING("ALERT: Threshold Violator Address = " << suspect.to_string() << " Packets sent within the last second is " << watermark << ". Automatic ban is disabled. Allowing this IP to bombard."); } } } } // // Reset // _packetCounter.clear(); _lastTime = now; } _packetCounterMutex.unlock(); }
void SIPFSMDispatch::onReceivedMessage(SIPMessage::Ptr pMsg, SIPTransportSession::Ptr pTransport) { if (!pTransport->isEndpoint() && pTransport->getLastReadCount() < MIN_DATAGRAM_SIZE && !pTransport->isReliableTransport()) { // // datagram is too short to be a SIP Message // Bailing out. Take note that streamed connection // can split SIP messages to smaller frames // and the last frame can be smaller than MIN_DATAGRAM_SIZE // so we do not impose a limit for streams // return; } try { pMsg->parse(); } catch(OSS::Exception e) { std::ostringstream logMsg; logMsg << "Incoming message failed to be parsed - " << e.message() << " LEN: " << pTransport->getLastReadCount() << " SRC: " << pTransport->getRemoteAddress().toIpPortString(); OSS::log_warning(logMsg.str()); return; } std::string id; if (!pMsg->getTransactionId(id)) return; // don't throw here // we don't have control over what we receive from the transport SIPTransaction::Ptr trn; SIPTransaction::Type transactionType = SIPTransaction::TYPE_UNKNOWN; if (pMsg->isRequest()) { if (OSS::string_caseless_starts_with(pMsg->startLine(), "invite")) { transactionType = SIPTransaction::TYPE_IST; if (_istBlocker.has(id)) { OSS_LOG_WARNING("Blocked request retransmission - " << pMsg->startLine()); return; } trn = _ist.findTransaction(pMsg, pTransport); } else if (OSS::string_caseless_starts_with(pMsg->startLine(), "ack")) { // // ACK for error responses will get matched to a transaction // transactionType = SIPTransaction::TYPE_IST; trn = _ist.findTransaction(pMsg, pTransport, false); } else { transactionType = SIPTransaction::TYPE_NIST; trn = _nist.findTransaction(pMsg, pTransport); } } else if (!pMsg->isRequest()) { std::string cseq; cseq = pMsg->hdrGet(OSS::SIP::HDR_CSEQ); if (OSS::string_caseless_ends_with(cseq, "invite")) { transactionType = SIPTransaction::TYPE_ICT; trn = _ict.findTransaction(pMsg, pTransport, false); } else { transactionType = SIPTransaction::TYPE_NICT; trn = _nict.findTransaction(pMsg, pTransport, false); } } if (trn) { std::ostringstream logMsg; if (!trn->getLogId().empty()) { logMsg << trn->getLogId() << "Found Transaction " << trn->getId(); OSS::log_debug(logMsg.str()); } else { trn->setLogId(pMsg->createContextId(true)); logMsg << trn->getLogId() << "Transaction " << trn->getId() << " CREATED"; OSS::log_information(logMsg.str()); } } if (!trn) { // // We did not get a transaction, check if this is an ack and find the IST ACK transaction // if (transactionType == SIPTransaction::TYPE_IST && pMsg->isRequest("ACK")) { // // No IST is existing in the ackable Pool. // Report this ACK as orphaned to the UA CORE // if (_ackOr2xxTransactionHandler) _ackOr2xxTransactionHandler(pMsg, pTransport); } else if (transactionType == SIPTransaction::TYPE_ICT && pMsg->is2xx()) { if (_ackOr2xxTransactionHandler) _ackOr2xxTransactionHandler(pMsg, pTransport); } else { std::ostringstream logMsg; logMsg << pMsg->createContextId(true) << "Unable to match incoming request to a transaction - " << pMsg->startLine(); OSS::log_warning(logMsg.str()); } } else { if (!trn->transportService()) { // // This is a newly created transaction // trn->transportService() = &_transport; trn->transport() = pTransport; } trn->onReceivedMessage(pMsg, pTransport); } }