Obsolete:Fundraising/tech/Spikes/Fundraiser 2012 412

From Wikitech
This page contains historical information. It may be outdated or unreliable.

Fundraising 2012 spike #412

See the spike #412 in mingle.

We have need of an IPA velocity filter for DonationInterface.

The AbuseFilter extension handles IP ranges; however, the tool they are using is Mediawiki's IP class.

As it turns it may not need very mush special code as this will just be doing a count from a database to obtain a rate from a time interval.

Requirements

  • define a limit of transactions per time interval for repeat IPAs
  • it would be helpful if a risk score was saved with each record
  • it might need the contribution tracking id
  • whitelist, blacklist and rate editable in LocalSettings
  • DO NOT VIOLATE PCI COMPLIANCE with storing to much information :)

Schema changes

This would require a table that would have the following fields:

  • `id` INTEGER
  • `ipa` INTEGER 4 bytes
  • `risk_score` DOUBLE
  • `contribution_tracking_id`
  • `created` DATETIME

It might be helpful to have built in garbage collection that deletes data after a specified lifetime.

This would prevent the table from growing to large over the course of a campaign.

Example as a filter function

This is an example of how to run an IP velocity filter as a custom filter function.

/**
 * This custom filter function checks the global variable:
 *
 * IpaMap
 *
 * How the score is tabulated:
 *  - If a IPA is blacklisted, a score of 100 will be generated. No further checks.
 *  - If a IPA is whitelisted, a score of zero will be generated. No further checks.
 *  - If a limit is defined, then count the occurences and generate a score.
 *  - Returns an integer: 0 <= $score <= 100
 *
 * @see GatewayAdapter::$debugarray
 * @see GatewayAdapter::log()
 *
 * @see $wgDonationInterfaceCustomFiltersFunctions
 * @see $wgDonationInterfaceIpaMap
 *
 * @return integer
 */
public function getScoreIpaMap() {

	// The score to return
	$score = 0;
	
	// Perform a check to generate a score
	$check = true;

	$ipa = wfGetIP();

	$ipaMap = $this->getGlobal( 'IpaMap' );

	$msg = self::getGatewayName() . ': IPA map: '
		. print_r( $ipaMap, true );

	$this->log( $msg, LOG_DEBUG );

	// Lookup blacklist
	if ( $check && isset( $ipaMap['blacklist'] ) ) {

		if ( in_array( $ipa, $ipaMap['blacklist'] ) ) {
			$score = 100;
			$check = false;
		}
	}
	
	// Lookup whitelist
	if ( $check && isset( $ipaMap['whitelist'] ) ) {

		if ( in_array( $ipa, $ipaMap['whitelist'] ) ) {
			$score = 0;
			$check = false;
		}
	}
	
	// Lookup the IPA in the database and calculate the score.
	if ( $check ) {

		$score = $this->getIpaCountScore( $ipa, $ipaMap );
	}

	// Save the IPA in the database
	$this->recordIpa( $ipa );

	// @see $wgDonationInterfaceDisplayDebug
	$this->debugarray[] = 'custom filters function: get ipa [ '
		. $ipa . ' ] map score = ' . $score;

	return $score;
}

Filtering by cidr notation

It might be helpful to whitelist or blacklist countries by cidr notation using the IP class

IP::isInRange( $ipa, '192.0.2.0/24')

Implementing this as a firewall

It is also possible to put this higher up in the stack to prevent a form from being displayed due to repeat attacks by the same IPA.