Running and working, then across the Great Wall, we can reach every corner in the world.

This commit is contained in:
Mengdi Gao 2015-01-25 22:44:57 +08:00
parent 9ca04a3cf2
commit 9093cdb8bb
5 changed files with 174 additions and 0 deletions

15
Dockerfile Normal file
View file

@ -0,0 +1,15 @@
FROM ubuntu:14.04
RUN apt-get update
RUN apt-get -y install strongswan iptables uuid-runtime
RUN rm /etc/ipsec.secrets
ADD ./etc/* /etc/
ADD ./bin/* /usr/bin/
VOLUME /etc
# http://blogs.technet.com/b/rrasblog/archive/2006/06/14/which-ports-to-unblock-for-vpn-traffic-to-pass-through.aspx
EXPOSE 500/udp 4500/udp
CMD /usr/bin/start-vpn

100
bin/generate-mobileconfig Executable file
View file

@ -0,0 +1,100 @@
#!/bin/bash
# TODO: add regenerate shared secret option
# In normal cases, you will only need to pass the HOST of your server.
[ "no${HOST}" = "no" ] && echo "\$HOST environment variable required." && exit 1
: ${PROFILE_NAME="My IKEv2 VPN Profile"}
: ${PROFILE_IDENTIFIER=$(echo -n "${HOST}." | tac -s. | sed 's/\.$//g')}
: ${PROFILE_UUID=$(hostname)}
# These variable, especially CONN_UUID, are bind to per username,
# which currently, all users share the same secrets and configurations.
: ${CONN_NAME="My IKEv2 VPN"}
: ${CONN_IDENTIFIER="${PROFILE_IDENTIFIER}.shared-configuration"}
: ${CONN_UUID=$(uuidgen)}
: ${CONN_HOST=${HOST}}
: ${CONN_REMOTE_IDENTIFIER=${HOST}}
CONN_SHARED_SECRET=$(cat /etc/ipsec.secrets | sed 's/.*"\(.*\)"/\1/g')
cat <<EOF
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<!-- Read more: https://wiki.strongswan.org/projects/strongswan/wiki/AppleIKEv2Profile -->
<plist version="1.0">
<dict>
<!-- Set the name to whatever you like, it is used in the profile list on the device -->
<key>PayloadDisplayName</key>
<string>${PROFILE_NAME}</string>
<!-- This is a reverse-DNS style unique identifier used to detect duplicate profiles -->
<key>PayloadIdentifier</key>
<string>${PROFILE_IDENTIFIER}</string>
<!-- A globally unique identifier, use uuidgen on Linux/Mac OS X to generate it -->
<key>PayloadUUID</key>
<string>${PROFILE_UUID}</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadVersion</key>
<integer>1</integer>
<key>PayloadContent</key>
<array>
<!-- It is possible to add multiple VPN payloads with different identifiers/UUIDs and names -->
<dict>
<!-- This is an extension of the identifier given above -->
<key>PayloadIdentifier</key>
<string>${CONN_IDENTIFIER}</string>
<!-- A globally unique identifier for this payload -->
<key>PayloadUUID</key>
<string>${CONN_UUID}</string>
<key>PayloadType</key>
<string>com.apple.vpn.managed</string>
<key>PayloadVersion</key>
<integer>1</integer>
<!-- This is the name of the VPN connection as seen in the VPN application later -->
<key>UserDefinedName</key>
<string>${CONN_NAME}</string>
<key>VPNType</key>
<string>IKEv2</string>
<key>IKEv2</key>
<dict>
<!-- Hostname or IP address of the VPN server -->
<key>RemoteAddress</key>
<string>${CONN_HOST}</string>
<!-- Remote identity, can be a FQDN, a userFQDN, an IP or (theoretically) a certificate's subject DN. Can't be empty.
IMPORTANT: DNs are currently not handled correctly, they are always sent as identities of type FQDN -->
<key>RemoteIdentifier</key>
<string>${CONN_REMOTE_IDENTIFIER}</string>
<!-- Local IKE identity, same restrictions as above. If it is empty the client's IP address will be used -->
<key>LocalIdentifier</key>
<string></string>
<!--
OnDemand references:
http://www.v2ex.com/t/137653
https://developer.apple.com/library/mac/featuredarticles/iPhoneConfigurationProfileRef/Introduction/Introduction.html
Continue reading:
https://github.com/iphoting/ovpnmcgen.rb
-->
<key>OnDemandEnabled</key>
<integer>1</integer>
<key>OnDemandRules</key>
<array>
<dict>
<key>Action</key>
<string>Connect</string>
</dict>
</array>
<!-- The server is authenticated using a certificate -->
<key>AuthenticationMethod</key>
<string>SharedSecret</string>
<key>SharedSecret</key>
<string>${CONN_SHARED_SECRET}</string>
<!-- The client uses EAP to authenticate -->
<key>ExtendedAuthEnabled</key>
<integer>0</integer>
</dict>
</dict>
</array>
</dict>
</plist>
EOF

14
bin/start-vpn Executable file
View file

@ -0,0 +1,14 @@
#!/bin/bash
# https://wiki.strongswan.org/projects/strongswan/wiki/ForwardingAndSplitTunneling
# Continue reading: https://wiki.strongswan.org/projects/strongswan/wiki/VirtualIP
sysctl net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -s 10.8.0.0/16 -o eth0 -m policy --dir out --pol ipsec -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.8.0.0/16 -o eth0 -j MASQUERADE
# hotfix for openssl `unable to write 'random state'` stderr
SHARED_SECRET="123$(openssl rand -base64 32 2>/dev/null)"
[ -f /etc/ipsec.secrets ] || echo ": PSK \"${SHARED_SECRET}\"" > /etc/ipsec.secrets
# http://wiki.loopop.net/doku.php?id=server:vpn:strongswanonopenvz
/usr/sbin/ipsec start --nofork

24
etc/ipsec.conf Normal file
View file

@ -0,0 +1,24 @@
# /etc/ipsec.conf - strongSwan IPsec configuration file
#
# Based on http://www.strongswan.org/uml/testresults/ikev2/rw-psk-ipv4/
config setup
conn %default
left=%defaultroute
ikelifetime=60m
keylife=20m
rekeymargin=3m
keyingtries=1
keyexchange=ikev2
authby=secret
conn rw
# http://wiki.loopop.net/doku.php?id=server:vpn:strongswanonopenvz
# https://wiki.strongswan.org/projects/strongswan/wiki/ForwardingAndSplitTunneling
leftsubnet=0.0.0.0/0
# end ref
leftfirewall=yes
right=%any
rightsourceip=10.8.0.0/16
auto=add

21
etc/strongswan.conf Normal file
View file

@ -0,0 +1,21 @@
# /etc/strongswan.conf - strongSwan configuration file
#
# strongswan.conf - strongSwan configuration file
#
# Refer to the strongswan.conf(5) manpage for details
#
# Configuration changes should be made in the included files
charon {
load_modular = yes
plugins {
include strongswan.d/charon/*.conf
# https://wiki.strongswan.org/projects/strongswan/wiki/Attrplugin
attr {
dns = 8.8.8.8, 8.8.4.4
}
}
}
include strongswan.d/*.conf