implement IpTrust

This commit is contained in:
Thibault Duplessis 2018-03-11 11:25:36 -05:00
parent a93f3724c2
commit 0e52dfa357
5 changed files with 45 additions and 24 deletions

View file

@ -135,19 +135,19 @@ object Auth extends LilaController {
case object Nope extends MustConfirmEmail(false)
case object YesBecausePrint extends MustConfirmEmail(true)
case object YesBecauseIp extends MustConfirmEmail(true)
case object YesBecauseProxy extends MustConfirmEmail(true)
case object YesBecauseIpExists extends MustConfirmEmail(true)
case object YesBecauseIpSusp extends MustConfirmEmail(true)
case object YesBecauseMobile extends MustConfirmEmail(true)
case object YesBecauseUA extends MustConfirmEmail(true)
def apply(print: Option[FingerPrint])(implicit ctx: Context): Fu[MustConfirmEmail] = {
val ip = HTTPRequest lastRemoteAddress ctx.req
api.recentByIpExists(ip) flatMap { ipExists =>
if (ipExists) fuccess(YesBecauseIp)
if (ipExists) fuccess(YesBecauseIpExists)
else print.??(api.recentByPrintExists) flatMap { printExists =>
if (printExists) fuccess(YesBecausePrint)
else if (HTTPRequest weirdUA ctx.req) fuccess(YesBecauseUA)
else Env.security.ipIntel(ip).map(80 <).map { _.fold(YesBecauseProxy, Nope) }
else Env.security.ipTrust.isSuspicious(ip).map { _.fold(YesBecauseIpSusp, Nope) }
}
}
}

View file

@ -98,7 +98,7 @@ final class Env(
lazy val garbageCollector = new GarbageCollector(
userSpyApi,
ipIntel,
ipTrust,
slack,
ugcArmedSetting.get,
system
@ -167,6 +167,8 @@ final class Env(
scheduler.once(30 seconds)(tor.refresh(_ => funit))
scheduler.effect(TorRefreshDelay, "Refresh Tor exit nodes")(tor.refresh(firewall.unblockIps))
lazy val ipTrust = new IpTrust(ipIntel, geoIP, tor, firewall)
lazy val api = new SecurityApi(storeColl, firewall, geoIP, authenticator, emailAddressValidator, tryOAuthServer)
lazy val csrfRequestHandler = new CSRFRequestHandler(NetDomain)

View file

@ -9,14 +9,13 @@ import lila.user.{ User, UserRepo }
// codename UGC
final class GarbageCollector(
userSpy: UserSpyApi,
ipIntel: IpIntel,
ipTrust: IpTrust,
slack: lila.slack.SlackApi,
isArmed: () => Boolean,
system: akka.actor.ActorSystem
) {
/* User just signed up and doesn't have security data yet,
* so wait a bit */
// User just signed up and doesn't have security data yet, so wait a bit
def delay(user: User, ip: IpAddress, email: EmailAddress): Unit =
if (!recentlyChecked.get(user.id) && user.createdAt.isAfter(DateTime.now minusDays 3)) {
recentlyChecked put user.id
@ -25,12 +24,12 @@ final class GarbageCollector(
}
}
private val recentlyChecked = new lila.memo.ExpireSetMemo(ttl = 5 minutes)
private val recentlyChecked = new lila.memo.ExpireSetMemo(ttl = 3 seconds)
private def apply(user: User, ip: IpAddress, email: EmailAddress): Funit =
userSpy(user) flatMap { spy =>
badOtherAccounts(spy.otherUsers.map(_.user)) ?? { others =>
lila.common.Future.exists(spy.ips)(isBadIp).map {
lila.common.Future.exists(spy.ips)(ipTrust.isSuspicious).map {
_ ?? {
val ipBan = spy.usersSharingIp.forall { u =>
isBadAccount(u) || !u.seenAt.exists(DateTime.now.minusMonths(2).isBefore)
@ -49,13 +48,6 @@ final class GarbageCollector(
(others.size > 1 && others.forall(isBadAccount) && others.headOption.exists(_.disabled)) option others
}
private def isBadIp(ip: UserSpy.IPData): Fu[Boolean] = if (ip.blocked ||
ip.location == Location.unknown ||
ip.location == Location.tor ||
ip.location.shortCountry == "Iran" // some undetected proxies
) fuccess(true)
else ipIntel(ip.ip).map { 75 < _ }
private def isBadAccount(user: User) = user.troll || user.engine
private def collect(user: User, email: EmailAddress, others: List[User], ipBan: Boolean): Funit = {

View file

@ -15,15 +15,9 @@ final class IpIntel(asyncCache: lila.memo.AsyncCache.Builder, lichessEmail: Stri
}
def failable(ip: IpAddress): Fu[Int] =
if (blackList.exists(ip.value.startsWith)) fuccess(90)
if (IpIntel isBlacklisted ip) fuccess(90)
else cache get ip
// Proxies ipintel doesn't detect
private val blackList = List(
"5.121.",
"5.122."
)
private val cache = asyncCache.multi[IpAddress, Int](
name = "ipIntel",
f = ip => {
@ -44,3 +38,14 @@ final class IpIntel(asyncCache: lila.memo.AsyncCache.Builder, lichessEmail: Stri
expireAfter = _.ExpireAfterAccess(3 days)
)
}
object IpIntel {
// Proxies ipintel doesn't detect
private val blackList = List(
"5.121.",
"5.122."
)
def isBlacklisted(ip: IpAddress): Boolean = blackList.exists(ip.value.startsWith)
}

View file

@ -0,0 +1,22 @@
package lila.security
import lila.common.IpAddress
case class IpTrust(intelApi: IpIntel, geoApi: GeoIP, torApi: Tor, firewallApi: Firewall) {
def isSuspicious(ip: IpAddress): Fu[Boolean] =
if (IpIntel isBlacklisted ip) yep
else if (firewallApi blocksIp ip) yep
else if (torApi isExitNode ip) yep
else {
val location = geoApi orUnknown ip
if (location == Location.unknown || location == Location.tor) yep
else if (location.shortCountry == "Iran") yep // some undetected proxies
else if (location.shortCountry == "United Arab Emirates") yep // some undetected proxies
else intelApi(ip).map { 75 < _ }
}
def isSuspicious(ipData: UserSpy.IPData): Fu[Boolean] = isSuspicious(ipData.ip)
private val yep = fuccess(true)
}