From 4983a9b24eac00b8d8bfd300a18cdcee0152a271 Mon Sep 17 00:00:00 2001 From: Kyle Drake Date: Fri, 7 Nov 2014 00:41:10 -0800 Subject: [PATCH] Cryptographically scramble IPs stored by Neocities "There is a time when the operation of the machine becomes so odious, makes you so sick at heart, that you can't take part; you can't even passively take part, and you've got to put your bodies upon the gears and upon the wheels, upon the levers, upon all the apparatus, and you've got to make it stop. And you've got to indicate to the people who run it, to the people who own it, that unless you're free, the machine will be prevented from working at all." Mario Savio Sproul Hall Steps University of California, Berkeley December 3, 1964 --- Gemfile | 1 + Gemfile.lock | 11 +++++++++-- Rakefile | 9 +++++++++ app.rb | 12 +++++++----- config.yml.template | 2 ++ environment.rb | 2 ++ models/site.rb | 31 ++++++++++++++++++++----------- tests/acceptance/signup_tests.rb | 2 ++ 8 files changed, 52 insertions(+), 18 deletions(-) diff --git a/Gemfile b/Gemfile index f250144a..99ab1cbe 100644 --- a/Gemfile +++ b/Gemfile @@ -24,6 +24,7 @@ gem 'sass', require: nil gem 'dav4rack' gem 'filesize' gem 'thread' +gem 'scrypt' platform :mri do gem 'magic' # sudo apt-get install file, For OSX: brew install libmagic diff --git a/Gemfile.lock b/Gemfile.lock index 436ef6bd..f6d17b97 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -54,7 +54,10 @@ GEM i18n (~> 0.5) faraday (0.9.0) multipart-post (>= 1.2, < 3) - ffi (1.9.3) + ffi (1.9.6) + ffi-compiler (0.1.3) + ffi (>= 1.0.0) + rake filesize (0.0.3) google-api-client (0.7.1) addressable (>= 2.3.2) @@ -133,7 +136,7 @@ GEM rack (~> 1.1) unicorn (~> 4.8) raindrops (0.13.0) - rake (10.2.1) + rake (10.3.2) redis (3.0.7) redis-namespace (1.4.1) redis (~> 3.0.4) @@ -146,6 +149,9 @@ GEM sass (3.3.8) screencap (0.1.1) phantomjs + scrypt (2.0.0) + ffi-compiler (>= 0.0.2) + rake sequel (4.8.0) sequel_pg (1.6.9) pg (>= 0.8.0) @@ -242,6 +248,7 @@ DEPENDENCIES ruby-debug sass screencap + scrypt sequel (= 4.8.0) sequel_pg shotgun diff --git a/Rakefile b/Rakefile index fb4371b1..e5042035 100644 --- a/Rakefile +++ b/Rakefile @@ -188,6 +188,15 @@ task :prime_site_updated_at => [:environment] do end end +desc 'hash_ips' +task :hash_ips => [:environment] do + Site.select(:id,:ip).order(:id).all.each do |s| + next if s.ip.nil? || s.ip.match(/#{$config['ip_hash_salt']}/) + s.ip = s.ip + s.save_changes validate: false + end +end + =begin desc 'Update screenshots' task :update_screenshots => [:environment] do diff --git a/app.rb b/app.rb index 49f40b7d..338c0dcd 100644 --- a/app.rb +++ b/app.rb @@ -1216,8 +1216,7 @@ post '/admin/banip' do flash[:error] = 'IP is blank, cannot continue' redirect '/admin' end - - sites = Site.filter(ip: site.ip, is_banned: false).all + sites = Site.filter(ip: Site.hash_ip(site.ip), is_banned: false).all sites.each {|s| s.ban!} flash[:error] = "#{sites.length} sites have been banned." redirect '/admin' @@ -1495,7 +1494,7 @@ post '/site/:username/report' do |username| redirect request.referer if current_site.id == site.id report.reporting_site_id = current_site.id else - report.ip = request.ip + report.ip = Site.hash_ip request.ip end report.save @@ -1533,8 +1532,8 @@ def dashboard_if_signed_in end def require_login_ajax - halt 'You are banned.' if Site.banned_ip?(request.ip) halt 'You are not logged in!' unless signed_in? + halt 'You are banned.' if current_site.is_banned? || parent_site.is_banned? end def csrf_safe? @@ -1546,8 +1545,11 @@ def csrf_token end def require_login - require_unbanned_ip redirect '/' unless signed_in? + if current_site.is_banned || parent_site.is_banned + session[:id] = nil + redirect '/' + end end def signed_in? diff --git a/config.yml.template b/config.yml.template index 1aba4e99..afb13194 100644 --- a/config.yml.template +++ b/config.yml.template @@ -8,6 +8,7 @@ development: sidekiq_pass: ENTER PASS HERE stripe_publishable_key: fillout stripe_api_key: fillout + ip_hash_salt: "400$8$1$fc21863da5d531c1" test: database: 'postgres://neocities@127.0.0.1/neocities_test' database_pool: 1 @@ -18,3 +19,4 @@ test: sidekiq_pass: ENTER PASS HERE stripe_publishable_key: fillout stripe_api_key: fillout + ip_hash_salt: "400$8$1$fc21863da5d531c1" \ No newline at end of file diff --git a/environment.rb b/environment.rb index 4095bccc..edc67d5c 100644 --- a/environment.rb +++ b/environment.rb @@ -26,6 +26,8 @@ else end # :nocov: +raise 'hash_ip_salt is required' unless $config['ip_hash_salt'] + DB = Sequel.connect $config['database'], sslmode: 'disable', max_connections: $config['database_pool'] DB.extension :pagination diff --git a/models/site.rb b/models/site.rb index 28bcc2e4..3c9e1dd9 100644 --- a/models/site.rb +++ b/models/site.rb @@ -202,20 +202,29 @@ class Site < Sequel::Model end def ip_create_limit?(ip) - Site.where('created_at > ?', Date.today.to_time).where(ip: ip).count > IP_CREATE_LIMIT || - Site.where(ip: ip).count > TOTAL_IP_CREATE_LIMIT + hashed_ip = hash_ip ip + Site.where('created_at > ?', Date.today.to_time).where(ip: hashed_ip).count > IP_CREATE_LIMIT || + Site.where(ip: hashed_ip).count > TOTAL_IP_CREATE_LIMIT + end + + def hash_ip(ip) + SCrypt::Engine.hash_secret ip, $config['ip_hash_salt'] + end + + def banned_ip?(ip) + return true if Site.where(is_banned: true). + where(ip: hash_ip(ip)). + where(['updated_at > ?', Time.now-BANNED_TIME]). + first + + return true if BlockedIp[ip] + + false end end - def self.banned_ip?(ip) - return true if Site.where(is_banned: true). - where(ip: ip). - where(['updated_at > ?', Time.now-BANNED_TIME]). - first - - return true if BlockedIp[ip] - - false + def ip=(ip) + super self.class.hash_ip(ip) end def is_following?(site) diff --git a/tests/acceptance/signup_tests.rb b/tests/acceptance/signup_tests.rb index 9eff5628..3ab21c5d 100644 --- a/tests/acceptance/signup_tests.rb +++ b/tests/acceptance/signup_tests.rb @@ -48,6 +48,8 @@ describe 'signup' do site.site_files.length.must_equal 4 site.site_changed.must_equal false site.site_updated_at.must_equal nil + + site.ip.must_equal Site.hash_ip('127.0.0.1') end it 'fails to create for existing site' do