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
This commit is contained in:
Kyle Drake 2014-11-07 00:41:10 -08:00
parent 1b7269c201
commit 4983a9b24e
8 changed files with 52 additions and 18 deletions

View file

@ -24,6 +24,7 @@ gem 'sass', require: nil
gem 'dav4rack' gem 'dav4rack'
gem 'filesize' gem 'filesize'
gem 'thread' gem 'thread'
gem 'scrypt'
platform :mri do platform :mri do
gem 'magic' # sudo apt-get install file, For OSX: brew install libmagic gem 'magic' # sudo apt-get install file, For OSX: brew install libmagic

View file

@ -54,7 +54,10 @@ GEM
i18n (~> 0.5) i18n (~> 0.5)
faraday (0.9.0) faraday (0.9.0)
multipart-post (>= 1.2, < 3) 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) filesize (0.0.3)
google-api-client (0.7.1) google-api-client (0.7.1)
addressable (>= 2.3.2) addressable (>= 2.3.2)
@ -133,7 +136,7 @@ GEM
rack (~> 1.1) rack (~> 1.1)
unicorn (~> 4.8) unicorn (~> 4.8)
raindrops (0.13.0) raindrops (0.13.0)
rake (10.2.1) rake (10.3.2)
redis (3.0.7) redis (3.0.7)
redis-namespace (1.4.1) redis-namespace (1.4.1)
redis (~> 3.0.4) redis (~> 3.0.4)
@ -146,6 +149,9 @@ GEM
sass (3.3.8) sass (3.3.8)
screencap (0.1.1) screencap (0.1.1)
phantomjs phantomjs
scrypt (2.0.0)
ffi-compiler (>= 0.0.2)
rake
sequel (4.8.0) sequel (4.8.0)
sequel_pg (1.6.9) sequel_pg (1.6.9)
pg (>= 0.8.0) pg (>= 0.8.0)
@ -242,6 +248,7 @@ DEPENDENCIES
ruby-debug ruby-debug
sass sass
screencap screencap
scrypt
sequel (= 4.8.0) sequel (= 4.8.0)
sequel_pg sequel_pg
shotgun shotgun

View file

@ -188,6 +188,15 @@ task :prime_site_updated_at => [:environment] do
end end
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 =begin
desc 'Update screenshots' desc 'Update screenshots'
task :update_screenshots => [:environment] do task :update_screenshots => [:environment] do

12
app.rb
View file

@ -1216,8 +1216,7 @@ post '/admin/banip' do
flash[:error] = 'IP is blank, cannot continue' flash[:error] = 'IP is blank, cannot continue'
redirect '/admin' redirect '/admin'
end end
sites = Site.filter(ip: Site.hash_ip(site.ip), is_banned: false).all
sites = Site.filter(ip: site.ip, is_banned: false).all
sites.each {|s| s.ban!} sites.each {|s| s.ban!}
flash[:error] = "#{sites.length} sites have been banned." flash[:error] = "#{sites.length} sites have been banned."
redirect '/admin' redirect '/admin'
@ -1495,7 +1494,7 @@ post '/site/:username/report' do |username|
redirect request.referer if current_site.id == site.id redirect request.referer if current_site.id == site.id
report.reporting_site_id = current_site.id report.reporting_site_id = current_site.id
else else
report.ip = request.ip report.ip = Site.hash_ip request.ip
end end
report.save report.save
@ -1533,8 +1532,8 @@ def dashboard_if_signed_in
end end
def require_login_ajax 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 not logged in!' unless signed_in?
halt 'You are banned.' if current_site.is_banned? || parent_site.is_banned?
end end
def csrf_safe? def csrf_safe?
@ -1546,8 +1545,11 @@ def csrf_token
end end
def require_login def require_login
require_unbanned_ip
redirect '/' unless signed_in? redirect '/' unless signed_in?
if current_site.is_banned || parent_site.is_banned
session[:id] = nil
redirect '/'
end
end end
def signed_in? def signed_in?

View file

@ -8,6 +8,7 @@ development:
sidekiq_pass: ENTER PASS HERE sidekiq_pass: ENTER PASS HERE
stripe_publishable_key: fillout stripe_publishable_key: fillout
stripe_api_key: fillout stripe_api_key: fillout
ip_hash_salt: "400$8$1$fc21863da5d531c1"
test: test:
database: 'postgres://neocities@127.0.0.1/neocities_test' database: 'postgres://neocities@127.0.0.1/neocities_test'
database_pool: 1 database_pool: 1
@ -18,3 +19,4 @@ test:
sidekiq_pass: ENTER PASS HERE sidekiq_pass: ENTER PASS HERE
stripe_publishable_key: fillout stripe_publishable_key: fillout
stripe_api_key: fillout stripe_api_key: fillout
ip_hash_salt: "400$8$1$fc21863da5d531c1"

View file

@ -26,6 +26,8 @@ else
end end
# :nocov: # :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 = Sequel.connect $config['database'], sslmode: 'disable', max_connections: $config['database_pool']
DB.extension :pagination DB.extension :pagination

View file

@ -202,20 +202,29 @@ class Site < Sequel::Model
end end
def ip_create_limit?(ip) def ip_create_limit?(ip)
Site.where('created_at > ?', Date.today.to_time).where(ip: ip).count > IP_CREATE_LIMIT || hashed_ip = hash_ip ip
Site.where(ip: ip).count > TOTAL_IP_CREATE_LIMIT 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
end end
def self.banned_ip?(ip) def ip=(ip)
return true if Site.where(is_banned: true). super self.class.hash_ip(ip)
where(ip: ip).
where(['updated_at > ?', Time.now-BANNED_TIME]).
first
return true if BlockedIp[ip]
false
end end
def is_following?(site) def is_following?(site)

View file

@ -48,6 +48,8 @@ describe 'signup' do
site.site_files.length.must_equal 4 site.site_files.length.must_equal 4
site.site_changed.must_equal false site.site_changed.must_equal false
site.site_updated_at.must_equal nil site.site_updated_at.must_equal nil
site.ip.must_equal Site.hash_ip('127.0.0.1')
end end
it 'fails to create for existing site' do it 'fails to create for existing site' do