Skip to content
This repository has been archived by the owner on Jun 22, 2024. It is now read-only.

Commit

Permalink
Feat/updated protocols (#10)
Browse files Browse the repository at this point in the history
* cleaned the code and added more protocols

* updated readme

---------

Co-authored-by: m.ahadi <[email protected]>
  • Loading branch information
M-Ahadi and m.ahadi authored Mar 12, 2023
1 parent c4b0605 commit 2967c17
Show file tree
Hide file tree
Showing 29 changed files with 1,313 additions and 1,190 deletions.
6 changes: 5 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ RUN yarn build


FROM python:3.11-slim
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
RUN apt update &&\
apt install --no-install-recommends -y \
nginx \
curl \
unzip \
openssl \
supervisor &&\
rm -f /var/www/html/* &&\
mkdir -p /etc/nginx/routes \
Expand Down Expand Up @@ -53,7 +56,8 @@ VOLUME /x-view/db
RUN apt remove -y \
unzip &&\
apt autoremove -y &&\
rm -rf /var/lib/apt/lists/*
rm -rf /var/lib/apt/lists/* &&\
mkdir /var/log/x-core

HEALTHCHECK --interval=30s --timeout=3s CMD ./healthcheck.sh

Expand Down
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
# X-View

X-View is an interface for [X-ray Core](https://github.com/XTLS/Xray-core) to make VPN configuration. This project is inspired by [x-ui](https://github.com/vaxilu/x-ui) project.
Currently, this project is in alpha state.


## Todos
- [ ] Clean the code!
- [ ] Test all configuration for all protocols
- [ ] Add option to put vpn behind nginx
- [ ] Add option to put vpn behind cloud
- [ ] Support multi-user
Expand All @@ -20,7 +18,6 @@ Currently, this project is in alpha state.
- [x] Supported protocols: vmess, vless, shadowsocks, trojan, dokodemo-door, socks, http
- [x] Support for configuring more transport configurations
- [x] Customizable xray configuration template
- [x] For more advanced configuration items, see Panel
- [x] Supports Google Captcha v2 for login authentication (enable from admin panel)
- [x] Configure web panel port in docker-compose.yml
- [x] Multilingual
Expand All @@ -30,6 +27,7 @@ Currently, this project is in alpha state.
- [x] Add certificate to nginx
- [X] Support Dark and Light Them

For more advanced configuration items, see Panel

![Menu](images/documentation/menu.jpg) \
Easy to use menu to access different sections, change them, and language
Expand Down
19 changes: 14 additions & 5 deletions backend/xview/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import logging
import platform
import subprocess

from django.contrib.auth.models import AbstractUser
Expand Down Expand Up @@ -47,13 +48,17 @@ class Meta:

@staticmethod
def restart_xray():
logger.info("restart xray service")
subprocess.Popen("/usr/bin/supervisorctl restart xray", shell=True)
if platform.system() == "Linux":
logger.info("restart xray service")
subprocess.Popen("/usr/bin/supervisorctl restart xray", shell=True)

@staticmethod
def create_config_json():
rules = {
"log": None,
"log": {
"loglevel": "warning",
"access": "/var/log/x-core/access.log"
},
"routing": {
"rules": [
{
Expand Down Expand Up @@ -137,12 +142,16 @@ def create_config_json():

for inbound in inbounds_list:
streamSettings = json.loads(inbound.transport)
if streamSettings['security'] == 'tls':
if streamSettings.get("security") == 'tls':
streamSettings['tlsSettings']['certificates'] = [{
"certificate": inbound.certificate.certificate.split(","),
"key": inbound.certificate.privatekey.split(","),
}]

if streamSettings.get("security") == 'xtls':
streamSettings['xtlsSettings']['certificates'] = [{
"certificate": inbound.certificate.certificate.split(","),
"key": inbound.certificate.privatekey.split(","),
}]
inbounds_config.append(
{
"listen": inbound.bindip,
Expand Down
10 changes: 4 additions & 6 deletions backend/xview/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,19 @@
from rest_framework import routers
from rest_framework_simplejwt import views as jwt_views

from .views import InboundViewSet, UserTokenObtainPairView, InboundStatusView, CertificateView, UserViewSet
from .views import InboundViewSet, UserTokenObtainPairView, InboundStatusView, CertificateView, UserViewSet, \
GenerateKeyView

router = routers.DefaultRouter()
router.register('inbounds', InboundViewSet)
router.register('status', InboundStatusView)
router.register('certificate', CertificateView)
router.register('change_password', UserViewSet)


app_name = 'xview_app'
urlpatterns = [

path('api/',include(router.urls)),
# path('api/login/', jwt_views.TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/', include(router.urls)),
path('api/generate_password/<int:key_length>/', GenerateKeyView.as_view()),
path('api/login/', UserTokenObtainPairView.as_view(), name='token_obtain_pair'),
path('api/token/refresh/', jwt_views.TokenRefreshView.as_view(), name='token_refresh'),
# url(r'^login_urls$',views.get_login_urls,name='get_login_urls'),
]
39 changes: 21 additions & 18 deletions backend/xview/views.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import logging

# Create your views here.
import platform

import subprocess
from django.shortcuts import get_object_or_404
from rest_framework import viewsets, status, filters
from rest_framework.views import APIView
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from captcha.models import Captcha
from .models import Inbound, Certificate, User
from .pagination import InboundPagination
from .permissions import UpdateOwnProfile
from .serializers import InboundSerializer, UserTokenObtainPairSerializer, InboundStatusSerializer, \
CertificateSerializer, UserSerializer
from .utils import check_captcha
Expand All @@ -21,34 +21,30 @@
class InboundViewSet(viewsets.ModelViewSet):
serializer_class = InboundSerializer
queryset = Inbound.objects.all()
# authentication_classes = (TokenAuthentication,)
permission_classes = (IsAuthenticated,)
pagination_class = InboundPagination

def destroy(self, request, *args, **kwargs):
id = kwargs.get("pk")
logger.info(f"Requested to delete inbound id {id}")
if id:
instance = Inbound.objects.filter(id=id).first()
if instance:
instance.delete()
logger.info(f"Inbound id {id} deleted.")
instance = get_object_or_404(Inbound, id=id)
instance.delete()
logger.info(f"Inbound id {id} deleted.")
return Response({}, status=status.HTTP_200_OK)
return Response({}, status=status.HTTP_400_BAD_REQUEST)
return Response({}, status=status.HTTP_404_NOT_FOUND)

def perform_update(self, serializer):
super(InboundViewSet, self).perform_update(serializer)
logger.info("Inbounds updated")
Inbound.create_config_json()
if platform.system() == "Linux":
Inbound.restart_xray()
Inbound.restart_xray()

def perform_create(self, serializer):
super(InboundViewSet, self).perform_create(serializer)
logger.info("An inbounds created")
Inbound.create_config_json()
if platform.system() == "Linux":
Inbound.restart_xray()
Inbound.restart_xray()


class InboundStatusView(viewsets.ModelViewSet):
Expand All @@ -62,8 +58,7 @@ def perform_update(self, serializer):
super(InboundStatusView, self).perform_update(serializer)
logger.info("Inbounds status updated")
Inbound.create_config_json()
if platform.system() == "Linux":
Inbound.restart_xray()
Inbound.restart_xray()


class CertificateView(viewsets.ModelViewSet):
Expand Down Expand Up @@ -92,12 +87,11 @@ def post(self, request, *args, **kwargs):
return Response({}, status=status.HTTP_400_BAD_REQUEST)



class UserViewSet(viewsets.ModelViewSet):
http_method_names = ["post"]
serializer_class = UserSerializer
queryset = User.objects.all()
permission_classes = (IsAuthenticated,)
permission_classes = (IsAuthenticated,UpdateOwnProfile,)
filter_backends = (filters.SearchFilter,)
search_fields = ('username',)

Expand All @@ -117,3 +111,12 @@ def create(self, request, *args, **kwargs):
else:
logger.error(serializer.errors)
return Response({}, status=status.HTTP_400_BAD_REQUEST)


class GenerateKeyView(APIView):
permission_classes = (IsAuthenticated,)

def get(self, request, key_length):
# result = subprocess.run(["/usr/bin/openssl","rand","-base64", str(key_length)], capture_output=True)
result = subprocess.run(["openssl", "rand", "-base64", str(key_length)], capture_output=True)
return Response({"password": result.stdout})
7 changes: 4 additions & 3 deletions frontend/src/components/inbounds/HttpForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
v-model="inbound_vars.name"
solo
density="compact"
></v-text-field>
/>
<v-row>
<v-col>
<v-text-field
Expand All @@ -17,7 +17,7 @@
v-model="inbound_vars.bindip"
solo
density="compact"
></v-text-field>
/>
</v-col>
<v-col>
<v-text-field
Expand All @@ -26,7 +26,8 @@
v-model="inbound_vars.port"
solo
density="compact"
></v-text-field>
type="number"
/>
</v-col>
</v-row>
<v-row>
Expand Down
Loading

0 comments on commit 2967c17

Please sign in to comment.